Automating Backups for Docker Volumes and Databases
#docker
#backup
#devops
#tutorial
Introduction
Backing up containerized workloads requires two parallel strategies: preserving the Docker volumes that hold persistent data, and capturing the databases that power your applications. This post walks through practical, repeatable methods to automate both in a way that scales with your environment. You’ll learn simple tar-based volume backups, reliable database dumps for MySQL and PostgreSQL, and a lightweight cron workflow to keep everything up to date.
Backing up Docker Volumes
Docker volumes store the data used by your containers. Because volumes are managed by the Docker daemon, the cleanest way to snapshot them is to mount the volume into a temporary container and tar the contents to a host directory.
Key ideas
- Use a temporary container to access the volume data without needing to modify your running containers.
- Compress backups and include a timestamp to simplify restores.
- Keep backups on durable storage, and consider encrypting sensitive backups if needed.
Example: backup a single named volume
#!/usr/bin/env bash
set -euo pipefail
VOLUME="myvolume" # named Docker volume to back up
BACKUP_DIR="${BACKUP_DIR:-./backups/volumes}"
mkdir -p "$BACKUP_DIR"
docker run --rm \
-v "$VOLUME":/data \
-v "$BACKUP_DIR":/backup \
alpine sh -c "tar czf /backup/${VOLUME}-$(date +%F).tar.gz -C /data ."
Example: backup multiple volumes
#!/usr/bin/env bash
set -euo pipefail
VOLUNTARY=("webdata" "dbdata" "logs") # list of Docker volumes to back up
BACKUP_DIR="${BACKUP_DIR:-./backups/volumes}"
mkdir -p "$BACKUP_DIR"
for vol in "${VOLUNTARY[@]}"; do
docker run --rm \
-v "$vol":/data \
-v "$BACKUP_DIR":/backup \
alpine sh -c "tar czf /backup/${vol}-$(date +%F).tar.gz -C /data ."
done
Restoring a Docker volume
- To restore, run a container that uses the backup tarball and extracts into the volume’s mount point.
#!/usr/bin/env bash
set -euo pipefail
VOLUME="myvolume"
BACKUP_DIR="./backups/volumes"
docker run --rm \
-v "$VOLUME":/data \
-v "$BACKUP_DIR":/backup \
alpine sh -c "tar xzf /backup/${VOLUME}-2025-07-14.tar.gz -C /data"
Notes
- If your volumes are attached to specific containers, you can also back up from a running container using —volumes-from, e.g. docker run —rm —volumes-from
-v “$BACKUP_DIR”:/backup alpine tar czf /backup/vol.tar.gz -C /data . - For very large volumes, consider incremental backup approaches or rsync-based diffing to reduce transfer size.
Backing up Databases in Docker
Databases in containers are critical and often have specific consistency requirements. The straightforward approach is to dump the databases and stream the output to your host backups.
MySQL (mariadb) backups
- Use mysqldump to dump all databases and stream to host storage, optionally gzip-compressing on the fly.
#!/usr/bin/env bash
set -euo pipefail
DB_CONTAINER="mysql"
MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-}"
BACKUP_DIR="${BACKUP_DIR:-./backups/databases}"
mkdir -p "$BACKUP_DIR"
# All databases for MySQL
docker exec "$DB_CONTAINER" mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --all-databases | gzip > "$BACKUP_DIR/mysql-all-dbs-$(date +%F).sql.gz"
PostgreSQL backups
- Use pg_dumpall (or pg_dump for selective databases) and gzip-compress the dump.
#!/usr/bin/env bash
set -euo pipefail
DB_CONTAINER="postgres"
BACKUP_DIR="${BACKUP_DIR:-./backups/databases}"
mkdir -p "$BACKUP_DIR"
# All databases for PostgreSQL
docker exec "$DB_CONTAINER" pg_dumpall -U postgres | gzip > "$BACKUP_DIR/postgres-all-dbs-$(date +%F).sql.gz"
Notes
- Store database credentials securely. Prefer environment variables, .my.cnf, or Docker secrets rather than embedding passwords in scripts.
- If your containers require a specific network or host access, ensure the backup command has the correct connectivity.
- For large databases, consider incremental dumps or logical backups combined with point-in-time recovery features where supported.
Example: a combined backup script
#!/usr/bin/env bash
set -euo pipefail
BASE="${BASE:-./backups}"
VOL_DIR="$BASE/volumes"
DB_DIR="$BASE/databases"
mkdir -p "$VOL_DIR" "$DB_DIR"
# Back up volumes
for vol in webdata cachedata; do
docker run --rm -v "$vol":/data -v "$VOL_DIR":/backup alpine sh -c "tar czf /backup/${vol}-$(date +%F).tar.gz -C /data ."
done
# Back up MySQL
docker exec mysql mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" --all-databases | gzip > "$DB_DIR/mysql-all-dbs-$(date +%F).sql.gz"
# Back up PostgreSQL
docker exec postgres pg_dumpall -U postgres | gzip > "$DB_DIR/postgres-all-dbs-$(date +%F).sql.gz"
A Simple End-to-End Cron Workflow
Automate daily backups by scheduling a single script that handles both volumes and databases.
Cron example (daily at 2am) 0 2 * * * /usr/local/bin/backup_all.sh
What to put in backup_all.sh
- The script should invoke both the volume backup logic and the database backup logic shown above.
- Ensure the script writes to a dedicated backups directory and rotates old backups if desired (e.g., keeping 30 days of tar.gz and sql.gz files).
Rotating backups (basic example)
# Rotate old volume backups (keep 30 days)
find ./backups/volumes -type f -name "*.tar.gz" -mtime +30 -delete
# Rotate old database backups (keep 30 days)
find ./backups/databases -type f -name "*.sql.gz" -mtime +30 -delete
Security and reliability notes
- Protect backup data with appropriate file permissions and, if needed, encryption in transit and at rest.
- Validate backups by performing test restores on a staging environment.
- Consider off-site or cloud storage for disaster recovery (e.g., rclone to a cloud bucket, or using a backup tool like restic).
Best Practices and Gotchas
- Separate backups by data type: volumes vs databases, so restoration is straightforward.
- Use timestamps in filenames to avoid overwriting previous backups.
- For large or mission-critical systems, implement incremental backups or dedicated backup tooling to reduce load and improve restore times.
- Regularly test restore procedures to ensure backups are usable.
- If you use bind mounts instead of Docker volumes, back them up similarly by tar-ing the mounted directory.
By combining simple tar-based volume snapshots with reliable database dumps, you can build a robust, automated backup workflow for Docker-based environments without paying for complex tooling.