 So I'm Alexander Dominikus from Bochum University of Applied Science, and I'm the Moodle administrator here also in Bochum. Okay, and today I want to talk about how to build your own Moodle Docker testing environments by using Docker. And before I start talking, I just want to give some sort of a trigger warning, since this talk is a little bit technical. So I want to give you some content of Docker files and Docker compose files and so on. But I want to please you please keep sitting. Since on the last slide you will find a link to my GitHub where I've sent all the examples and so on. So you can have a look if you want it just. Yeah, this is okay. So some working. Yes. Okay. About this talk. First, in the first part of the talk, I want to introduce you how to build a minimal Moodle via Docker. So this is the basis for the second part where I give you a few examples how to do some modifications. So in this, for example, if you want a PHP admin or if you want a Chrome process or whatever, and this is the second step. But first, before I start to introduce you how to build your minimal Moodle environment, I want to spend a few words about Docker in general. So why should you use Docker containers at all? So to answer this question, one should understand the aim of Docker containers. So Docker containers are made to make an application portable and self contained. So that means a Docker container is an encapsulation of an application and which has its own isolated instance of an operating system. And this Docker container is living on a host system. And from this encapsulation we have that changes on the host system won't change anything on a Docker containers. And in case of testing scenarios, this is exactly what you want. Since regardless on the host system, you have identical testing systems and this is in testing, this is exactly what you need and what you want. And also you can avoid a whole class of bugs and errors which are stemming in classical setup from changes on the host system. So imagine you are in a classical setup, you don't have any Docker containers, then you change something on the host system and this will lead you to changes on the testing environments and you will get some crazy bugs and errors and you have to find them. But if you use Docker containers, you won't have all these bugs and errors. So my advice is to use Docker containers if you want to spend your time for testing and not for certain bugs. Okay. Next, if you decide to use Docker, then you have to decide if you choose a pre-built Docker testing environment or if you build your own testing environment. If you build a pre-built one, if you use a pre-built one, then you can, for example, choose this excellent one model Docker testing environment for Moodle HQ or for example, Bitnami Moodle and there are so many more examples. And if you choose this pre-built one, then you can start instantly. Since it's pre-configured, it's pre-built and you can directly start testing. But imagine at some point you want to modify something, then it could be a really hard task to do these modifications. Since the modifications you want to do depends on the complexity on the testing environment. And so this could be really hard. On another hand, if you choose a self-built system, then you start with a minimal Moodle system and then you add everything you need. So you end up with a perfectly adapted testing environment and you also know this testing environment perfectly since it was you who made this testing environment. For sure you have to learn Docker before you start to build your own minimal Moodle testing environment, but nevertheless this is the way we want to go here. So next point is how to start. So first we have to install Docker and Docker compose because this is the basis for our work. Then we have to think about our needs. Since we want the minimal Moodle testing environment, meaning that we only want the necessary things to run Moodle. So we have to look at the system requirements. So the system requirements say we need the PHP language of at least version 7.3. We need a database. We choose the MariaDB database which is just for simplicity and which should be of version at least 10.2.29. All this is depending on the version, Moodle version 4.0.3. And for sure you need a web server to have access to your Moodle system. Okay, these are the three basic ingredients which will build your minimal Moodle testing environment. And these are the three services which we now add to our Docker compose file. So now what is the Docker compose file? Okay, a Docker compose file is just a plain text file. In this case it is a general file. And in this Docker compose file you define all your single services and also the configuration of each service. So let's have a look at this Docker compose file. So here we start with the Docker compose version. In this case it is version 2. We could also choose version 3. But version 2 is a little bit more simple. And then we add the services. So this is the database service, the PHP service and the web server. So the engine service. In the end we also define a network which is for the communication between each of these services. And in principle that's it. So now let's have a look at the definition of each single service. So here it is the database service. In the beginning you choose the image. This is just the MariaDB image. So what is an image? An image is the basis for Docker container. So an image has everything inside which is needed to build a Docker container. And once you have this Docker container you can run it and then you have a running MariaDB database. So that's it. We have this restart option meaning that in case of a crash or in case of an error this container should restart. Then we give the container a name and we have some environment variables. So in this case this is the MySQL user. It is the password for the MySQL user. And it is the database. So this is the Moodle database in this case which is created when a container is built. Here I have to say in sake of security this is not optimal since we define the MySQL user and the MySQL password in the plain text file and this is in principle this is a security risk. But this is only for testing and not for production system. So this is okay. If we want to do it more secure then we could add Docker secrets but I think in this case this is as simple as possible. Moreover we have here some volumes and what is the volume? So as I said before this Docker container is an encapsulation which is living on some host system. And if you create a database inside the Docker container then and then crash the Docker container or shut it down then all the data will be lost. So we create the database outside the container on the host system and therefore the data will be persist when the container shuts down. Moreover you have this configuration file which is for the configuration of the database which for example has these characters set and so on. And we have the port for the communication and the network for the communication with the other services. So this is a database service. Next we have the PHP service and here we don't have an image but we have a Docker file. I would say in a minute what's behind this Docker file. But first I will say something about the remaining configuration points. So here we also give the container a name and here we again have some volumes. So this is the Moodle folder which is living on the host system. This is the Moodle data folder which is also living on the host system. And we have the PHP configuration file which is the PHP in here which is also living on the host system. And there you can do some changes on these configuration files without entering your Docker container. So here the last option is the new option which is meaning that if the PHP container starts then it has to wait for the database to be running since it depends on it. It depends on it. Okay. So now let's have a closer look at these PHP Docker files. So what's behind this PHP Docker file? So what's behind this PHP Docker file? So in principle we could choose a PHP image here since we want the PHP service. But remembering that the Moodle system needs some PHP extensions to be installed. For example this is the this curl or zip or gd or mb string or whatever. And imagine that your PHP image does not have all these extensions installed originally then you have to add them. So what do we do? So we take this PHP image and then in this example here you install the zip program. And after that you add the PHP extension zip. And in the same way you can add every single PHP extension which is not contained in the PHP image originally. So we can fulfill all these requirements here. And that's all the magic of this Docker file. Okay the last point is the web server. Here in this case this is the engine x image. So we have an engine x web server. We could use an Apache server the same way but an engine x server is a little bit more light white. So I choose this one. We give the container a name and we have a configuration file on the host system. Which is which does the configuration for each engine x web server identical. Moreover we have a port. This is port 8088 where we have access to the web server and the principle that's it. So we have to save this Docker compose file and then run the containers. So if we run the container then we see that the network is created. All the containers will be built and then started and then we can check if we have access to the model system at localhost port 8088. And if we check it we see okay we have a running minimum model system at localhost 8088. And in principle it was quite easy. So this is just the basis for our work. Now we have a minimum model system but we have to do some customizations now. So next step is to add a PHP admin which is just an example. You can add everything you want here. So how do you add a PHP admin? So first you have to shut down your containers and then you have to enter your Docker compose file. In your Docker compose file you simply add your PHP admin service. So here are the three remaining services of your minimal model and then you add your PHP admin service. So you choose the PHP admin image, you give the container a name and you define a port where you want to have access to your PHP admin. Moreover you have to say the PHP admin where to find the model database and in this example this is simply the name of the model database service. So again that's it. We have defined a PHP admin service. So let's test if we have access to PHP admin and if we enter localhost port 8089 we see we have a PHP admin and again this was quite easy. So now next task is a little bit more challenging. We want to have a Chrome process. So each model system needs a Chrome process to run properly. So we want to add it. So what is a Chrome process? A Chrome process is just a PHP script which is running regularly. A PHP script is meaning we have to choose a PHP image. But how can we do that this PHP image is running regularly? And to answer this question we will have a look at this Docker file here. So what do we do? We choose a PHP image and then we use the Chrome program. So in a Unix board if you want to do some schedule task or some yeah some regulatory if you want to run some scripts here regularly or so on you use the Chrome program. So we install the Chrome program inside the container and then we can define a Chrome tab. And in this Chrome tab it's just defined that PHP should run this Chrome.php which is living in the Moodle folder every minute and that's it. Finally we simply have to say that this Chrome program has to run when the container starts and that's it. So for the sake of completeness look at the remaining configuration points. So here we have these volumes from option and this meaning that we give the Docker Moodle Chrome service access to the volumes of the Docker Moodle app. And in principle this service need access to the Moodle folder since in the Moodle folder is the Chrome.php script living. So moreover we have a volume on the host system where you find log files. This is just a nice feature. This is not necessary. Okay and in principle again that's it. We have to save this Docker compose file and then check if we have a running Chrome process. So we start the containers and then we check the logs of these Docker Moodle Chrome service. And if we check them then we see we have an executed schedule task one. We have an executed schedule task two and so on and so on. And this meaning that we have a running Chrome process and again this was quite easy. So the last point I want to add is a reverse proxy. So why do we need a reverse proxy? Remembering that we had these Moodle system as we have access to the Moodle system at local host port 8088 and we have access to PHP management at local host port 8089. So now imagine we have 20 different Moodle testing systems on the local machine then you have to remember all these ports and this will drive you crazy. So moreover if you want to have online access to your minimal Moodle then you have to expose all these ports to the internet and this is really a security risk. So I would advise you not to do this. Instead we want to use a reverse proxy. So what is a reverse proxy? In this case our reverse proxy is traffic and traffic is also living in a Docker container and traffic will lead you to the matching service. So what does it mean? We define a rule so in this case it's just a URL and we say we want to have access to our minimal Moodle system via the URL Moodle.local host and traffic will lead us to this service. Moreover we want to have access to our PHP management via the URL PMA.local host and traffic will do it for you. So this is in principle what reverse proxy do. So this also means that you don't have to expose all the ports. You just have to expose these ports 80 and port four for three which are the standard ports. So how can we add this reverse proxy? First we have to shut down all the containers again and then we have to set up traffic which is a reverse proxy. How do we set up traffic? I don't want to explain how to do this here but if you're interested in it you can look at my Github and you'll find a little example about the setup. So imagine we have a running reverse proxy and then we enter our docker compose file. So now we have the configuration of the engine X service which is the web server. First we have exposed the ports here but we don't want to expose any ports so we remove the ports and instead we add some labels and in this label we define that we want to have access to the web server via the URL Moodle.local host and that's it. We have one additional thing we have to do is to define another network which is the network which is needed for the communication with the reverse proxy. So again save this docker compose file and see if we have access to the minimal Moodle and we see we can access our minimal Moodle at Moodle.localhost and again it was not so hard task. So this was the last example and finally I have to say thank you for your attention. And if you're still interested in it you can look at the examples at my Github and yeah I just have to say are there any questions? Thank you. About how much RAM should I plan on using for that docker container that you've set up? Please repeat. How much memory should I expect to use for that docker container you've set up? In principle it is the same amount of memory if you install this set up in the classical way. So if you use an Apache server and the database and so on so in principle it is not more memory. The only problem you have is if you have more than one testing environment then in the classical way you just copy the whole environment folder and then you have an additional engine X server, you have an additional database and you have an additional web server. So in the classical way you can use some different testing environments on one web server but in this set up you have a web server, a database and a PHP for every testing environment and then you need some more memory but in principle you can compare it to the classical set up.