Backup and Restore
Named volumes are managed by Docker, so you cannot access them directly with cp without root access. The standard approach is to use a temporary container that mounts the volume and creates a portable archive.
Backup: Volume → Tar Archive
docker run --rm \
-v my-data:/source:ro \
-v $(pwd):/backup \
alpine \
tar cvf /backup/my-data-backup.tar -C /source .
This creates my-data-backup.tar in your current directory containing everything in the my-data volume.
How It Works
flowchart LR
subgraph Temp["Temporary Alpine Container"]
S["/source (volume, read-only)"]
B["/backup (current dir)"]
S -->|"tar cvf"| B
end
V["Named Volume:<br/>my-data"] --> S
B --> F["my-data-backup.tar"]
style V fill:#e8f5e9,stroke:#2e7d32
style F fill:#e3f2fd,stroke:#1565c0
| Flag | Purpose |
|---|---|
--rm | Delete the temporary container after it finishes |
-v my-data:/source:ro | Mount the volume as read-only (safe) |
-v $(pwd):/backup | Bind mount the current directory to write the archive |
alpine | Tiny image (5MB) with tar included |
Restore: Tar Archive → Volume
Step 1: Create the Target Volume
docker volume create my-data-restored
Step 2: Extract the Archive into the Volume
docker run --rm \
-v my-data-restored:/dest \
-v $(pwd):/backup \
alpine \
tar xvf /backup/my-data-backup.tar -C /dest
The my-data-restored volume now contains the backup data. Point your container at this volume to use it.
Migration: Host A → Host B
To move a volume between servers:
flowchart LR
A["Host A"] -->|"1. Backup to tar"| T["my-data-backup.tar"]
T -->|"2. scp to Host B"| B["Host B"]
B -->|"3. Restore to volume"| V["New Volume"]
style T fill:#fff3e0,stroke:#ef6c00
# On Host A: Create the backup
docker run --rm -v my-data:/source:ro -v $(pwd):/backup alpine \
tar cvf /backup/my-data-backup.tar -C /source .
# Transfer to Host B
scp my-data-backup.tar user@host-b:~/
# On Host B: Create volume and restore
docker volume create my-data
docker run --rm -v my-data:/dest -v ~/:/backup alpine \
tar xvf /backup/my-data-backup.tar -C /dest
Database Backups: Use Native Tools
For databases, it is often safer to use the database's own dump tools rather than backing up raw data files. This ensures consistency (no half-written transactions):
| Database | Backup Command | Restore Command |
|---|---|---|
| PostgreSQL | docker exec db pg_dump -U postgres mydb > backup.sql | docker exec -i db psql -U postgres mydb < backup.sql |
| MySQL | docker exec db mysqldump -u root -p mydb > backup.sql | docker exec -i db mysql -u root -p mydb < backup.sql |
| Redis | docker exec redis redis-cli BGSAVE then copy the RDB file | Copy RDB file back into the data directory |
When to Use Which Method
- Volume backup (tar): Good for file-based data (uploads, configs, static assets)
- Database dump: Better for databases -- ensures transactional consistency
- Both: For maximum safety, do both
Key Takeaways
- Back up volumes using a temporary Alpine container with
tar-- it is portable and requires no root access on the host. - Mount the source volume as read-only (
:ro) during backups for safety. - For databases, prefer native dump tools (
pg_dump,mysqldump) over raw file backups. - To migrate volumes between hosts: backup → transfer → restore.
- Test your restores regularly. A backup you have never restored is not a backup.
What's Next
- Return to the Volumes, Bind Mounts, and Data Lifecycle module overview.
- Continue to Module 7: Docker Compose to learn how to manage multi-service applications.