How to Backup WordPress Database and Directory Docker Containers

In this tutorial, I am going to show you how to backup Docker containers for services WordPress and MySQL in a docker-compose.yml file. If you read enough backup articles like me, you will find that some articles relate to just backing up a container as an image without the data volumes and others on both docker image plus volumes. Since we are dealing with WordPress here, it is necessary to backup the data volumes.

Backup WordPress Files and Database

This is how a typical docker-compose.yml for WordPress looks like.

version: '3.7'

services:
  db:
    image: mysql:8.0.19
    container_name: db
    ...
    volumes: 
      - dbdata:/var/lib/mysql
    ...

  wordpress:
    depends_on: 
      - db
    image: wordpress:5.4.0-php7.4-fpm-alpine
    container_name: wordpress
    ...
    volumes:
      - ./wordpress:/var/www/html
    ...

Backup Container as Image (optional)

As you can see, we execute docker commit -p wordpress wp-backup to backup the WordPress container (container name: wordpress) as an image (backup name: wp-backup). When we execute docker images again, we can see that there is an additional image which is our backup image wp-backup. This backup has a file size of 201MB similar to the current WordPress image which was pulled from Docker Hub two weeks ago. Thus, this shows that files (e.g. themes and plugins) in the WordPress directory are not included in the backup image and you are just making an exact copy of what is already available on Docker Hub.

user@server:~/wordpress-docker$ docker images
REPOSITORY              TAG                       IMAGE ID            CREATED             SIZE
wordpress               5.4.0-php7.4-fpm-alpine   78ac3963ff95        2 weeks ago         201MB
mysql                   8.0.19                    9228ee8bac7a        2 weeks ago         547MB
nginx                   1.17.9-alpine             377c0837328f        6 weeks ago         19.7MB

user@server:~/wordpress-docker$ docker commit -p wordpress wp-backup
sha256:10f73e5ecac57f7e3800020d9a30f66acc74c59797ed7440cc90537c2a658d2a

user@server:~/wordpress-docker$ docker images
REPOSITORY              TAG                       IMAGE ID            CREATED             SIZE
wp-backup               latest                    10f73e5ecac5        11 seconds ago      201MB
wordpress               5.4.0-php7.4-fpm-alpine   78ac3963ff95        2 weeks ago         201MB
mysql                   8.0.19                    9228ee8bac7a        2 weeks ago         547MB
nginx                   1.17.9-alpine             377c0837328f        6 weeks ago         19.7MB

Step 1 – Backup WordPress Database with mysqldump

We will use mysqldump to dump out the WordPress database instead of doing a full backup of dbdata:/var/lib/mysql which is the entire MySQL filesystem and a total directory size of 237MB.

user@server:~/wordpress-docker$ docker exec -i db ls -l /var/lib/mysql
total 217620
drwxr-x--- 2 mysql mysql     4096 Apr 10 19:00 #innodb_temp
-rw-r----- 1 mysql mysql       56 Apr 10 07:30 auto.cnf
-rw-r----- 1 mysql mysql  3102175 Apr 10 07:30 binlog.000001
-rw-r----- 1 mysql mysql  2313794 Apr 10 17:42 binlog.000002
-rw-r----- 1 mysql mysql     4382 Apr 10 19:00 ib_buffer_pool
-rw-r----- 1 mysql mysql 50331648 Apr 16 04:03 ib_logfile0
-rw-r----- 1 mysql mysql 50331648 Apr 16 04:03 ib_logfile1
-rw-r----- 1 mysql mysql 12582912 Apr 16 04:03 ibdata1
-rw-r----- 1 mysql mysql 12582912 Apr 10 19:00 ibtmp1
drwxr-x--- 2 mysql mysql     4096 Apr 10 07:30 mysql
-rw-r----- 1 mysql mysql 30408704 Apr 16 04:03 mysql.ibd
-rw-r----- 1 mysql mysql 12582912 Apr 16 04:03 undo_001
-rw-r----- 1 mysql mysql 12582912 Apr 16 04:03 undo_002
drwxr-x--- 2 mysql mysql     4096 Apr 10 07:45 wordpress
...

user@server:~/wordpress-docker$ docker exec -i db du -sh /var/lib/mysql
237M    /var/lib/mysql

We can achieve this by docker exec and replacing db with your database container name. For example, my wordpress-backup.sql from a two weeks old WordPress with a couple of posts and plugins etc. is only 3MB. Note that single quotes are required to escape the password with special characters.

docker exec db mysqldump -uwp_databaseuser -p'wp_databasepassword' wordpress > wordpress-database-backup.sql

Step 2 – Backup WordPress wp-config.php, Themes and Plugins Directory etc.

wp-config.php is stored in docker-project/wordpress folder and downloaded themes and plugins are stored in docker-project/wordpress/wp-content folder. Irregardless, we will backup the entire WordPress directory.

2a. The Docker Way
Here we run a temporary (–rm) WordPress container with pulled image wordpress:5.4.0-php7.4-fpm-alpine and mount the volume from –volumes-from wordpress (existing container name) into this temporary container. This will create the directory /var/www/html where WordPress files and directories reside in, inside the container. Then we use the -v flag to mount our current server directory $(pwd) as /backup (in the temporary container). Lastly, we execute the tar compress command in the container and the final backup file wordpress-files-backup.tar.gz will be stored in our actual server directory ($pwd).

docker run --rm --volumes-from wordpress -v $(pwd):/backup wordpress:5.4.0-php7.4-fpm-alpine tar zcvf /backup/wordpress-files-backup.tar.gz /var/www/html

2b. Using tar command
I was left wondering why can’t I just tar up the whole WordPress directory in docker-project/wordpress? So, I decided to try this simply by using tar.

tar zcvf wordpress-files-backup.tar.gz docker-project/wordpress

Are both backups from 2a and 2b the same?
I copied both tar.gz files created by docker and tar command respectively from remote webserver to my local desktop. Then untar them to their folder and ran WinMerge to compare both directories. The result was both tar.gz files are identical!

WinMerge compare WordPress files

Conclusion

It is pretty straightforward that we dump the WordPress database regularly for our backup strategy, more often than we need to backup the WordPress directory unless one adds new themes and plugins frequently. That being said, I will go opt for the tar method which I am more familiar with to backup the WordPress directory. There is a one liner tar zcvf – docker-project/wordpress | ssh user@server “cat > /path/to/backup/wordpress-files-backup.tar.gz” which you can add to cron to transfer wordpress-files-backup.tar.gz to another backup server easily.

Leave a Reply

Your email address will not be published. Required fields are marked *