/docker-compose-wordpress-nginx-mysql

Docker Compose: WordPress on MySQL and NGINX with Certbot

GNU General Public License v2.0GPL-2.0

Docker Compose: WordPress on MySQL and NGINX with Certbot

This multi-container Docker app is orchestrated with Docker Compose for rapid and modular deployment that fits in any microservice architecture.

It creates a WordPress website on a MySQL database and an NGINX web server, with Certbot by the Electronic Frontier Foundation (EFF) for obtaining and renewing a signed SSL/TLS certificate on a given root domain from Let’s Encrypt, a non-profit Certificate Authority by the Internet Security Research Group (ISRG).

A detailed walk-through is available here.

Table of Content

Getting Started

Get started in three simple steps:

  1. Download a copy of the app;
  2. Create the environment variables for the MySQL root password and the WordPress database settings; and
  3. Docker Compose to start the app.

Git Clone

Download a copy of the app with git clone. Be sure to pass the --recurse-submodules argument to initialise and update each submodule in the repository.

$ git clone --recurse-submodules https://github.com/kurtcms/docker-compose-wordpress-nginx-mysql /app/docker-compose-wordpress-nginx-mysql/

Environment Variables

Docker Compose expects the MySQL root password, the WordPress database name, username and password as environment variables in a .env file in the same directory.

Be sure to create the .env file.

$ nano /app/docker-compose-wordpress-nginx-mysql/.env

And define the variables accordingly.

# MySQL root password
MYSQL_ROOT_PASSWORD='(redacted)'

# WordPress database name, username and password
MYSQL_WORDPRESS_DATABASE='kurtcms_org'
MYSQL_WORDPRESS_USER='kurtcms_org'
MYSQL_WORDPRESS_PASSWORD='(redacted)'

Docker Compose

With Docker Compose, the app may be provisioned with a single command.

Install

Install Docker and Docker Compose with the Bash script that comes with app.

$ chmod +x /app/docker-compose-wordpress-nginx-mysql/docker-compose/docker-compose.sh \
    && /app/docker-compose-wordpress-nginx-mysql/docker-compose/docker-compose.sh

SSL/TLS Certificate

A dummy SSL/TLS certificate and private key will need to be created for NGINX to start service, and for Certbot to subsequently obtain a signed SSL/TLS certificate from Let's Encrypt by answering a HTTP-01 challenge.

Create the dummy certificate before obtaining a signed one with the Bash script that comes with app.

$ chmod +x /app/docker-compose-wordpress-nginx-mysql/certbot/certbot.sh \
    && /app/docker-compose-wordpress-nginx-mysql/certbot/certbot.sh

Enter the root domain and the email address for registration and recovery when prompted.

Up and Down

Start the containers with Docker Compose.

$ docker-compose -f /app/docker-compose-wordpress-nginx-mysql/docker-compose.yml up -d

Stopping the containers is as simple as a single command.

$ docker-compose -f /app/docker-compose-wordpress-nginx-mysql/docker-compose.yml down

Backup and Restore

With the Docker containers up and running, WordPress will be reachable at the localhost address on TCP port 443 i.e. HTTPS, to which TCP port 80 i.e. HTTP will be redirected. Follow the instructions on screen to set up WordPress. Alternatively the MySQL database and WordPress content can be restored from an existing backup.

Docker Volume

The MySQL database, the WordPress content as well as the signed SSL/TLS certificate and its corresponding private key are stored in separate Docker volume under /var/lib/docker/volumes/.

/var/
└── lib/
    └── docker/
        └── volumes/
            ├── docker-compose-wordpress-nginx-mysql_certbot/
            ├── docker-compose-wordpress-nginx-mysql_mysql/
            └── docker-compose-wordpress-nginx-mysql_wordpress/

MySQL

MySQL comes with a tool for logical backup. It produces a set of SQL statements that can be executed to reproduce the original database object definitions and table data.

Back up an existing MySQL database in a container.

$ docker exec -it mysql mysqldump \
    --user root \
    --password \
    kurtcms_org > kurtcms_org.sql

Restore a database from an existing backup.

$ docker exec -it mysql mysql \
    --user root \
    --password \
    kurtcms_org < kurtcms_org.sql

WordPress

WordPress plugins and themes, as well as media files uploaded by users are housed under wp-content in the WordPress directory. Backing up and restoring them is as simple as making a copy of this directory and moving it to the WordPress container.

Making a copy of the wp-content directory.

$ cp -r /var/lib/docker/volumes/docker-compose-wordpress-nginx-mysql_wordpress/_data/wp-content \
    /app/docker-compose-wordpress-nginx-mysql/

Restoring it from an existing backup.

$ cp -r /app/docker-compose-wordpress-nginx-mysql/wp-content/ \
    /var/lib/docker/volumes/docker-compose-wordpress-nginx-mysql_wordpress/_data/

SSL/TLS Certificate Renewal

Certbot is instructed by Docker Compose to attempt a SSL/TLS certificate renewal every 12 hours, which should be more than adequate considering the certificate is valid for 90 days.

NGINX is instructed to reload its configuration every 24 hours to ensure the renewed certificate will come into effect at most 12 hours after a renewal, which should also be well in advance of an impending expiry.

Edit the docker-compose.yml should these intervals need to be adjusted.

$ nano /app/docker-compose-wordpress-nginx-mysql/docker-compose.yml

Modify the values as appropriate.

  nginx:
    ...
    command: "/bin/sh -c 'while :; do sleep 24h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

  certbot:
    ...
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

Reference