loading...

May 10, 2020

WordPress via Docker

Kubernetes has taken over the world by storm with it’s powerful container application groups (they call them Pods). The common act of placing multiple containers beside each other in the simplest fashion can be done using Docker’s own Docker Compose utility.

Running this site, I didn’t want to have to deal with administering a MySQL database, a WordPress instance, and the Apache web server. Naturally, I wanted to take advantage of containers to do just that. By utilizing containers I’m able to take advantage of a properly configured environment with minor tweaking to ensure both the MySQL database and WordPress configuration files are preserved whenever I need to mess around with the service (such as configuration changes requiring a full application group restart, or simply updating the application containers to ensure I’m running the latest and greatest security patches)

So how does it all come together? Easier than writing a DockerFile! Checkout this sample docker-compose.yml:

version: '2'

services:
   db:
     image: mysql:5.7
     volumes:
       - /srv/db:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: oranges-sometimes-clever-fall
       MYSQL_DATABASE: wordpress-blog
       MYSQL_USER: wp-user
       MYSQL_PASSWORD: never-cycling-footprint-hooligan

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     volumes:
       - /srv/html:/var/www/html
     ports:
       - "80:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_PASSWORD: never-cycling-footprint-hooligan
volumes:
    db_data:

This configuration file fires up two containers:

  • WordPress (latest)
  • MySQL 5.7

The WordPress container is the official latest, meaning it is already configured with Apache and will write all its files to /var/www/html inside the container. In the above configuration, the volumes list will create a container volume for that container path on the container’s host volume under /srv/html. This way any file writing inside the container will persist outside of it. The configuration also exposes WordPress on the container host port 80 (host-port:container-port). The database container will write its database files to /var/lib/mysql inside the container. Just like the WordPress container, we will expose a container volume to the container host path /srv/db. Both containers have environment variables to be populated with database passwords and accounts. By default WordPress wants to use the wp-user account.

Now that we have our application group configured, you can bring it up by executing docker-compose up -d inside the directory with docker-compose.yml. This is very easy to use, the two commands we’ll be interested in are up and down, with the up taking a -d flag to detach and allow the daemon to run in the background. When you start to realize the power of Docker Compose in your every day tasks, you’ll start throwing more and more of these into the mix. You’re going to need to identify these different application groups, otherwise you’ll keep replacing your old ones with your new ones. Application group names can be passed via the -p flag. It’s best practice to always supply this flag!

What if you want to run multiple WordPress blogs on your hosted VM? Create a configuration file for each of your blogs just like above, but make sure to change the container host port (the first 80 in 80:80) and change it to something like 8080. Ensure each WordPress has its own unique IP, we can use Nginx to transparently proxy for us.

Create an nginx.conf configuration file to transparently forward your container host port 80 requests to the appropriate container application group:

user nobody nogroup;
worker_processes auto;

events {
  worker_connections 512;
}

http {
    server {
      listen       80;
      server_name  first.domain.com;

      location / {
        proxy_pass http://:8080/;
        proxy_set_header Host $host;
      }
    }

    server {
      listen       80;
      server_name  second.domain.com;

      location / {
        proxy_pass  http://:8081/;
        proxy_set_header Host $host;
      }
    }
}

I’ve seen a lot of bad advice on setting this up out there. After many failed attempts and some reasoning and experimentation this is the simplest configuration so far. Each WordPress domain will have its own Server entry in the configuration. They will all listen on port 80, and will forward proxy the request to the specified Public IP and designated port number. This is a standalone Docker container, so starting it is very simple:

docker run —name wp-proxy -v /srv/proxy/nginx.conf:/etc/nginx/nginx.conf:ro -p 0.0.0.0:80:80 -d nginx
Posted in DevOps
Write a comment