If you want to setup a containerized WordPress and MySQL environment, one solution is to use docker compose. Below I’ll first show you the complete docker-compose.yml file and later we’ll go through it line by line.

You can also find this code on github. If you want to check it out.

version: "3.8"

services:
  db:
    image: mysql:latest
    volumes:
      - ./db/data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: database
      MYSQL_USER: username
      MYSQL_PASSWORD: password

  wordpress:
    image: wordpress:latest
    depends_on:
      - db
    volumes:
      - ./wp/wp-content:/var/www/html/wp-content
      # Add other files or folders that you want to override here e.g. stylesheets
    ports:
      - "8880:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: database
      WORDPRESS_DB_USER: username
      WORDPRESS_DB_PASSWORD: password

Yaml basics

First of, in case you haven’t seen Yaml before it’s a data serialization language designed to be human readable. We often see it in configuration files as an alternative for json and XML. Yaml is based of a key-value structure where the text to the left of the colon is the key, and the text to the right is the value. The value can also be another key or an array of values, in that case we write them on a new line, and if it’s an array value we prefix it with a dash and a space. Note that Yaml files rely heavily on indentation to keep the structure in the file, and it’s case sensitive.

Version

The first line in the docker-compose.yml file is the version. This line is optional but it describes what file format version we want to use. If you remove this line it will default to the latest one. It’s usually recommended to use the latest version, which at the time of writing is 3.8.

version: "3.8"

Services

Unlike version, services must be part of your Yaml file. It describes what kind of services we are going to use in our project. In this case we want to use a database service and a WordPress service. We can name our services arbitrarily, but it’s recommended to name them somewhat logical depending on their function. In this example we named the database service db and the WordPress service wordpress.

services:
  db:
    # settings for the db service
  wordpress:
    # settings for the wordpress service

Database service

First of we will setup our database. In this example we will use MySQL but WordPress can also use MariaDB.

services:
  db:
    image: mysql:latest
    volumes:
      - ./db/data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpass
      MYSQL_DATABASE: database
      MYSQL_USER: username
      MYSQL_PASSWORD: password

Each service needs an image, since we decided to use MySQL we chose the mysql:latest image. At the time of writing this is MySQL 8.x, if you rather prefer MySQL 5.7 you can replace latest with 5.7.

The next key is volumes, here we tell docker if we want to mount any files or directories inside our container. Since we want our database to have persistent data we need to mount a directory inside the directory where MySQL saves data. This means that in the same directory as our docker-compose.yml we need to create a directory db with a subdirectory data. This will be where all MySQL data will be stored.

If we want our service to start up automatically after for example a reboot we can use the restart key with the value always. Other alternatives are no, on-failure, and unless-stopped. Their functions are pretty self explanatory.

Lastly in the db service we have the environment key. Here we simply list the environment variables we want inside the container. These specific environment variables are only used if the mounted directory is empty, i.e. when we setup the database. Make sure to change the values to what makes sense in your project.

WordPress service

Now we’ll take a look at the WordPress service, this basically follows the same pattern. A few differences to note here are depends_on and ports.

services:
  db:
    # Database service settings	

  wordpress:
    image: wordpress:latest
    depends_on:
      - db
    volumes:
      - ./wp/wp-content:/var/www/html/wp-content
      # Add other files or folders that you want to override here e.g. stylesheets
    ports:
      - "8880:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: database
      WORDPRESS_DB_USER: username
      WORDPRESS_DB_PASSWORD: password

The image we’ll use for our WordPress service is wordpress:latest, this image at the time of writing uses PHP 7.4.15, Apache Webserver 2.4.38, and WordPress 5.6.1.

Next up is the depends_on key, as it sounds it is used to set up dependencies between services. We can do this a bit more advanced if we want, but when using the short syntax like in the example above the wordpress service will be created after the db service, and if we remove the services the wordpress service will be destroyed before the db service.

If we want to be able to upload files, and install themes or plugins in our WordPress site, we need to be able to store files in the wp-content directory. So to be able to persist these files if we need to restart the container we need to mount the directory in our container. Like with the db/data directory we need to create a directory named wp, in the same directory as the docker-compose.yml file, with the subdirectory wp-content.

We also need to be able to access the web server in our service, so we use the ports key to map a local port to a port inside the container. Make sure to use a free port on the host machine, e.g. 8880 in this case.

In the environment variables inside our environment key, we can see that we reference the db service inside the WORDPRESS_DB_HOST. This works since the services in the Yaml file are put inside their own network. This means that we can connect to the database service by just knowing the name. So you don’t have to figure out the IP of the container you want to connect to.

Starting the containers

To start the containers open a terminal in the directory where you have your Yaml file and type:

docker-compose up -d

You should now be able to access your WordPress site at http://localhost:8880 or whatever port you chose. You can now run through the installation wizard and start using WordPress.


Featured image by Naji Habib from Pixabay

Published by Jimmie

Jimmie is a full stack developer with over 13 years working experience in building web based solutions and over 25 years of programming experience over all. Jimmie has worked with a slew programming languages over the years, but his main focus is usually on web frameworks such as Symfony,  Angular, and Spring Boot.

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: