Backup, migration, and recovery with WordPress and Docker Compose

It seems that I’m recording an inordinate amount of information concerning WordPress and Docker. This is, as usual, at the behest of my wife. She likes WordPress and I love her, so what can I do?

The benefit of all this WordPress/Docker monkey business is that I’m slowly discovering my own best practices concerning both. What follows is the next installment of my self-education.

Context

I had to do a mass migration of my myriad web applications. My wife’s sites were not spared the inconvenience. They all had been previously Dockerized, so it was really just a matter of doing a backup of the WordPress files and MySQL data and sending it over to a new server in the cloud. The server, of course, had Docker, Compose, et al already installed. The whole setup looked a little like this:

[System Topology]

Backup

This is the process I followed to backup the sites hosted on the system to be turfed.

WordPress

This bundles up all the WordPress container files into a single, zipped tar ball.

1
docker run --rm --volumes-from mysitecom_wordpress_1 -v $(pwd):/backup wordpress tar zcvf /backup/mysitecom_wordpress.tar.gz /var/www/html

MySQL

I don’t bother copying all the container files here. I just need a dump of the WordPress database. Peripheral files are unnecessary and unwanted.

1
docker exec -i mysitecom_mysql_1 mysqldump -uroot -psecretp@ssword wordpress > mysitecom_mysql.sql

Setup

Prep the site’s new home. Here I put Docker Compose to good use managing the running containers. I set up two peripheral data-only containers that do not execute. These are not defined in the docker-compose.yml file as a way of shielding the site’s data from accidental deletion.

First, create a directory and docker-compose.yml:

1
2
3
mkdir mysite.com
cd mysite.com
vim docker-compose.yml

Copy and save the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
wordpress:
image: wordpress
restart: always
links:
- mysql
environment:
- WORDPRESS_DB_PASSWORD=secretp@ssword
- VIRTUAL_HOST=mysite.com
expose:
- 80
volumes_from:
- mysitecom_wordpress_data
mysql:
image: mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=secretp@ssword
- MYSQL_DATABASE=wordpress
volumes_from:
- mysitecom_mysql_data

Note the VIRTUAL_HOST variable. This site is (and was) running behind an nginx-proxy image.

Next, create the non-executing data-only containers. These are kept at arm’s length from the running containers so that our data doesn’t go up in smoke whilst monkeying around with image upgrades and whatnot.

MySQL

1
docker create --name mysitecom_mysql_data -v /var/lib/mysql mysql

WordPress

1
docker create --name mysitecom_wordpress_data -v /var/www/html wordpress

It’s now safe to fire up the running containers:

1
docker-compose up -d

At this point, if you were to visit the site URL, you should see WordPress inviting you to set everything up. I, however, have existing site data.

Recovery

The backup files created above have been copied over to the new server and into my working directory (i.e., the one containing docker-compose.yml). Write those files to the running containers. All the data actually gets sent to the non-executing, data-only containers because of how we set up docker-compose.yml.

WordPress

1
docker run --rm --volumes-from mysitecom_wordpress_1 -v $(pwd):/backup wordpress tar zxvf /backup/mysitecom_wordpress.tar.gz -C /

MySQL

1
docker exec -i mysitecom_mysql_1 mysql -uroot -psecretp@ssword wordpress < mysitecom_mysql.sql

You should now be able to see your old site on its new server.