 So when I thought about developing for WordPress, I thought about having to configure Apache and MySQL and all these things and it actually kind of scared me. And then I thought this would be a really good opportunity to finally look into Docker and learn how Docker works in both local development and for deployment and all these things. And in the end, I have to say I have no regrets. It turned out to be a really great setup. And I want to show you how it works so you can even run this entire setup on your machine locally. Before we dive in, just keep in mind that I didn't just pull this out of a hat at the very start. This is a result of many iterations on my end and lots of failure and lots of frustration. But in the end, I had a setup that I really like. And before we start, I think I should make sure that we all know what Docker actually is. Docker is a way to run virtual machines and not just virtual emulated machines, but actually containers like isolated from the host system. And we're going to have two of these containers running, one for Apache, PHP and the WordPress code and one for the database, which is MySQL. We can put these containers in their own little virtual network so they only can talk to each other and to nothing else and also no other Docker container that might be running can talk to them. And we're only going to expose port 8080 from the Apache machine because that's where the web server is running and that's the thing that we want to talk to. So you configure these virtual machines by writing so-called Docker files. So in this case, we need to write two Docker files, one for Apache on PHP and WordPress and one for MySQL. So let's start with the MySQL container. We can use the official MySQL image and if we read through the readme, we will actually find a command that we can just copy paste and just adjust to our needs. The only thing that we need to change is set the password for the root account and we need to add it to a network so that we have it in isolation where we can later add on the Apache. So we can just change the command accordingly. One of the things we need to keep in mind is that these containers are volatile. So there should be throwaway and recreatable at any point in time without creating a disturbance in the system. So any kind of data that we want to persist between these tear downs and recreation phases, we need to persist to the host system and that's where volumes come into play. Which basically is mounting a directory from the host system into the container. And in this case, we're going to store all of MySQL data in one of these mounted folders. The other container for Apache, PHP and WordPress, we can actually use the official WordPress image which already takes care of configuring Apache and PHP to work together as WordPress expects and just serves up WordPress for you. Again, the only thing we need to worry about is to add the network flag so that the MySQL container and the WordPress container can talk to each other. And if we run this command, you can already see that WordPress is being served up and is completely working, which I thought was pretty amazing with just two containers. But for my development flow, I wanted to have something more. I wanted to have HB2 because it makes websites so much faster. So to achieve that, I wanted to add a third container that runs Kettie. Kettie is an HB2 server that runs as a reverse proxy and has a very tight integration with Let's Encrypt. So in this case, I would run it as a reverse proxy in front of Apache and expose a new port to it. In this case, it would be 8443. And that means that on the port A443, I would get the entire app served over HB2 with a locally signed CLS certificate while on 8080, the old HB1 version would be served up. Okay, once again, we start with reading the readme of the image that we are going to use. We can copy paste the command and just need to do little adjustments. Once again, we have the port. In this case, we have the configuration file for Kettie and we have, as always, the network flag so that Kettie ends up in the same network as all our other two containers. For the configuration file for Kettie, we need to define where the requests are supposed to go. So we need to use Kettie's proxy command to tell that all incoming requests are supposed to be forwarded to a machine called PWP, which is the machine that runs Apache PHP and WordPress. Additionally though, we need to add some headers to the forward request because the backend needs to know that even though it's receiving HTTP requests that they were originally actually HTTPS and that enables a slightly different machinery inside WordPress. This is the only bit where we need to monkey patch a little bit inside WordPress, but that's because that's how their official wiki is documenting this process and they don't have this HTTP handling built in. Then we need to tell Kettie that we want to use a self-sign certificate. So we don't actually want to go to Let's Encrypt but just create a certificate yourself for local development, that's fine. If we were to go to production, we could just remove that line and Kettie would actually request a real sign certificate from Let's Encrypt and the entire machinery would just work even on a real server, which kind of blew my mind that we can just use the exact same setup for local development and for production. So if we run this additional third machine, you can see that we now have the exact same effect as before that everything is working, but this time it's now over HTTP2, which is amazing. However, we now have three individual machines that we need to configure and that can get quite cumbersome. And this is where so-called orchestration comes into play. For orchestration, Docker has to command Docker Compose. We write a Compose file to describe how all your individual machines are supposed to work together. So this is what really makes this thing really frictionless. To write a Docker Compose file, we just create a new YAML file. Docker Compose clusters are always in their own little network, so we don't need to worry about the network flag anymore. And now it's basically just a list of the machines that we need. So the first service in our Docker Compose file is the MySQL service. And we're going to define the MySQL password, the image to use, and the volume you want to mount that holds all the MySQL data. The second service is the WordPress image with Apache and PHP, which also needs the MySQL password and the port to listen on. And the third service now is Caddy, which needs the image, the configuration file for Caddy, and the second port that we want to expose to the host machine. So this configuration file we can now save and run with a command Docker Compose up. And as you can see, if you run this command, we immediately have our entire system set up and we can just start using WordPress out of the box. So we use Docker to define our development environment and can just spin it up and tear it down with just one command. But also we can use it in production, which I think is pretty great. Next time, we're going to write our very first lines of PHP and I'm really excited about that. So if you want to see that, subscribe to this channel and I will see you next time.