I want to backup a dockerized wordpress.

Ordinarily I'd restore a docker app from backups like this:

  • spin up a new database container
  • restore a sql dump to the database container
  • spin up a new app container
  • copy backup files to app container (e.g. in /var/www/html/)

...and ordinarily I'd upgrade a docker app like this:

  • stop the app container
  • update app's image: foo:1.23 version number in docker-compose.yml
  • restart app container

But this isn't simple with wordpress - it has a self-update feature, and the docs recommend backing up all of /var/www/html/* which is overkill and messy, and essentially is a backup of the app itself rather than just the user's files.

So to give me that workflow, I was planning to backup:

  • config files on host: .env, docker-compose.yml, docker secrets, ini/conf files, etc.
  • mariadb container: a sql dump
  • wordpress container: custom theme from /var/www/html/wp-content/themes/custom/

What other files must I backup (in app container's /var/www/html/ path), so I can safely restore backups and perform docker-style upgrades? What files should I include to ensure all plugins' settings/etc. are backed up as well?


Solution 1:

My Wordpress uses a separate container for the database which I configured in my docker-compose.yml file:

version: '3'


services:
   db:
     container_name: ${CONTAINER_DB_NAME}
     image: mariadb:latest
     restart: unless-stopped
     volumes:
        - ${DB_PATH}:/var/lib/mysql
     environment:
       MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
       MYSQL_DATABASE: ${MYSQL_DATABASE}
       MYSQL_USER: ${MYSQL_USER}
       MYSQL_PASSWORD: ${MYSQL_PASSWORD}


   wordpress:
     depends_on:
       - db
     container_name: ${CONTAINER_WP_NAME}
     image: wordpress:latest
     restart: unless-stopped
     volumes:
       - ${WP_CORE}:/var/www/html
       - ${WP_CONTENT}:/var/www/html/wp-content
       - ./conf.d/uploadsize.ini:/usr/local/etc/php/conf.d/uploadsize.ini
     environment:
       WORDPRESS_DB_HOST: ${CONTAINER_DB_NAME}:3306
       WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
       WORDPRESS_DB_USER: ${MYSQL_USER}
       WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
       WORDPRESS_TABLE_PREFIX: ${WORDPRESS_TABLE_PREFIX}
       VIRTUAL_HOST: ${DOMAINS}
       LETSENCRYPT_HOST: ${DOMAINS}
       LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL} 


networks:
    default:
       external:
         name: ${NETWORK}

I then on a daily basis connect to the database using another instance of the same container:

sudo docker exec db /usr/bin/mysqldump -u my_db_user --password=my_db_pass my_wp_database > /var/wp_backups/my_wp_database_backup.sql

The wp_backups folder is a git repo, so after running the dump I add the file to git and commit / push. This does nothing if the file has not changed and will push the changes when it has changed:

git add .
git commit -a -m "$(date '+%Y-%m-%d')"
git push