Skip to main content

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
FlagPurpose
--rmDelete the temporary container after it finishes
-v my-data:/source:roMount the volume as read-only (safe)
-v $(pwd):/backupBind mount the current directory to write the archive
alpineTiny 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):

DatabaseBackup CommandRestore Command
PostgreSQLdocker exec db pg_dump -U postgres mydb > backup.sqldocker exec -i db psql -U postgres mydb < backup.sql
MySQLdocker exec db mysqldump -u root -p mydb > backup.sqldocker exec -i db mysql -u root -p mydb < backup.sql
Redisdocker exec redis redis-cli BGSAVE then copy the RDB fileCopy 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