Automated Docker Compose Backups
This guide shows a simple way to create automated backups of your Docker Compose folders using a lightweight Docker container and rsync.
The approach is intentionally simple:
- One backup container
- One scheduled nightly backup
- Backup copies stored on another disk or NAS
- No external backup software required
This works well for homelab environments and small self-hosted setups.
What This Backs Up
This guide backs up:
- Docker Compose files
- Container configuration folders
- Application data volumes
- Environment files
- Stack folders under /docker
Example:
/docker/
├── jellyfin
├── vaultwarden
├── homeassistant
├── immich
└── paperless
Create the Project Folder
mkdir -p ~/docker/docker-backups
cd ~/docker/docker-backups
Create the Docker Compose File
Create:
nano docker-compose.yml
Paste:
services:
docker-backups:
image: alpine
container_name: docker-backups
restart: unless-stopped
volumes:
- /docker:/docker:ro
- /mnt/backups/docker:/backup
entrypoint: /bin/sh
command: |
-c '
apk add --no-cache rsync tzdata busybox-suid
cat << "EOF" > /backup-script.sh
#!/bin/sh
DATE=$$(date +%F)
DEST=/backup/$$DATE
mkdir -p $$DEST
rsync -a --delete /docker/ $$DEST
find /backup -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;
EOF
chmod +x /backup-script.sh
echo "30 1 * * * /backup-script.sh" > /etc/crontabs/root
crond -f -l 8
'
Start the Backup Container
Run:
docker compose up -d
How It Works
This setup:
- Runs a lightweight Alpine Linux container
- Installs rsync
- Creates a nightly cron job
- Copies /docker into dated backup folders
- Automatically removes backups older than 30 days
Example backup structure:
/mnt/backups/docker/
├── 2026-05-25
├── 2026-05-26
├── 2026-05-27
└── latest
Recommended Backup Location
Avoid storing backups on the same physical disk as the original Docker data.
Better options include:
- A second SSD
- External USB storage
- Synology NAS
- Another server
- Network share
Restoring a Backup
To restore:
- Stop the affected containers
- Copy the backup data back into /opt/docker
- Restart the containers
Example:
docker compose down
rsync -a /backup/2026-05-25/jellyfin/ /opt/docker/jellyfin/
docker compose up -d
Notes
- This is a file-level backup approach
- Databases may benefit from application-aware backups
- Nightly backups are sufficient for many homelab environments
- rsync is efficient and only copies changed files
Advanced Example (Reference Only)
This is my current backup container setup.
It is more advanced than most users require, but may provide useful ideas for larger homelab environments.
services:
docker-backups:
image: alpine
container_name: docker-backups
stop_grace_period: 30s
restart: unless-stopped
environment:
- TZ=America/Santo_Domingo
volumes:
- /opt/docker:/docker:ro
- /mnt/sjb2/docker-backups/micropc:/backup
entrypoint: /bin/sh
command: |
-c '
apk add --no-cache rsync tzdata busybox-suid
cat << "EOF" > /backup-script.sh
#!/bin/sh
DATE=$$(date +%F)
DEST=/backup/$$DATE
LAST=/backup/latest
mkdir -p $$DEST
if [ -d "$$LAST" ]; then
rsync -a --delete --no-owner --no-group --link-dest=$$LAST /docker/ $$DEST
else
rsync -a --delete --no-owner --no-group /docker/ $$DEST
fi
rm -f /backup/latest
ln -s $$DEST /backup/latest
find /backup -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;
EOF
chmod +x /backup-script.sh
echo "30 1 * * * /backup-script.sh" > /etc/crontabs/root
crond -f -l 8
'