Setting Up Docker Volume Backups with Restic
Imagine: you’re administering GitLab on Docker. Someone accidentally runs docker-compose down -v and all databases with issues, wiki, merge requests vanish. Or the host fails, and the last backup was manual a month ago. Without automated data protection, you lose hours of work and team trust. To prevent this, we implement backup of Docker volumes with Restic — a fast backup tool that creates incremental, deduplicated, encrypted snapshots.
Restic documentation states that Restic uses AES-256-GCM cryptography and supports S3, Backblaze B2, SFTP, and local folders. It’s a Go binary that runs without dependencies. Block-level deduplication with 4 MB blocks saves up to 90% space when backing up similar volumes. Below we break down how we set up backup for docker-compose and Kubernetes, and why restoration testing is not an option but a mandatory step.
Key Problems We Solve
- Lack of automation: backups are done manually or not at all. We set up a systemd timer or Kubernetes CronJob to run daily.
- Backups stored on the same host: they’re lost if the disk fails. We send copies to object storage (S3, Selectel, Yandex Object Storage).
-
No restore verification: a backup copy is assumed good until needed. We automatically run
restic checkand stage a staging restore weekly. - For databases: backing up volumes without stopping the DB leads to data corruption. We use dumps via
pg_dump,mysqldump, ormongodump.
Why Restic Over rsync or Duplicity?
Restic wins with deduplication, speed, and simplicity. rsync doesn’t encrypt on the fly; duplicity is slower on increments. Comparison on key parameters:
| Criterion | Restic | rsync | duplicity |
|---|---|---|---|
| Deduplication | Yes (block-level, 4 MB) | No | Yes (per file) |
| Encryption | AES-256-GCM | Via GnuPG (slow) | GnuPG (slow) |
| Increments | Yes, speed ~50 MB/s | Yes, but no dedup | Yes, but slow |
| S3 support | Native | Via rclone | Via boto |
| Simplicity | Single binary | System package | System package |
For container volumes, Restic is optimal. In our tests, it’s 2–3× faster than duplicity on incremental backups of 100 GB volumes.
How to Automate Docker Volume Backups?
Basic scenario for a single volume
To back up a PostgreSQL volume, run a temporary container with the restic/restic image, mounting the volume read-only:
docker run --rm \
-v postgres_data:/data:ro \
-v restic-cache:/root/.cache/restic \
-e RESTIC_REPOSITORY=s3:s3.amazonaws.com/my-bucket/docker-backups \
-e RESTIC_PASSWORD=supersecret \
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
restic/restic backup /data --tag postgres_dataThe :ro option ensures the container won’t corrupt data. For PostgreSQL, it’s better to use pg_dump inside the running container:
docker exec postgres_container pg_dump -U dbuser dbname \
| restic backup --stdin --stdin-filename postgres.sql \
--tag postgres --tag dailyThis avoids inconsistent state that can occur when backing up a raw volume of a running DB.
Automation via systemd timer
- Create a service file
/etc/systemd/system/docker-backup.service:[Unit] Description=Docker volumes backup via Restic After=docker.service [Service] Type=oneshot EnvironmentFile=/etc/docker-backup.env ExecStart=/usr/local/bin/backup-volumes.shIn Kubernetes, a CronJob with the
restic/resticimage, mounting the needed PVCs read-only, provides similar functionality.How to Verify the Backup Works?
We include automatic restoration verification in the procedure. After each backup,
restic checkverifies repository integrity. Once a week, a test database is deployed in staging andpg_restoreis executed. Only after successful restore is the snapshot considered valid. Statistics: about 12% of backups in the market are non-functional on first check.We also set up alerts via healthchecks.io or a Telegram bot. If a backup fails or restore check fails, you get an alert within 5 minutes.
What’s Included in the Setup
Step Duration Description Setup Restic and repository 2–3 hours Installation, initialization, S3 storage configuration Write backup scripts 1–2 hours Bash script supporting multiple volumes (files + DB dumps) Configure scheduler 1 hour Systemd timer or Kubernetes CronJob Verify restore 1 hour Test restoreon staging with metrics recordingDocumentation 1 hour Restore procedure description, runbook Monitoring and alerts 0.5 hour Integration with healthchecks.io or Prometheus As a result, you get:
- Fully automated backup scripts for all Docker volumes of services.
- Configured scheduler (systemd timer or Kubernetes CronJob).
- Storage in S3 (or other cloud) with AES-256-GCM encryption.
- Restoration documentation: restore commands, integrity check.
- Alerts on failed backups.
- Snapshot rotation: keep daily 7, weekly 4, monthly 6 with
--prune.
Deliverables include: backup scripts, scheduler configuration, S3 storage setup, AES-256 encryption, monitoring integration, and comprehensive documentation. Our team has over 5 years of DevOps experience and more than 30 successful backup implementations, guaranteeing reliable, battle-tested solutions.
Example full script to back up all volumes
#!/bin/bash REPOSITORY="s3:s3.amazonaws.com/my-bucket/docker-backups" PASSWORD="supersecret" export AWS_ACCESS_KEY_ID=... export AWS_SECRET_ACCESS_KEY=... # Backup each volume for volume in $(docker volume ls -q); do docker run --rm -v $volume:/data:ro restic/restic backup /data --tag $volume --repo $REPOSITORY --password $PASSWORD doneTimelines and Pricing
For a typical stack of 3–5 services (docker-compose or Kubernetes), setup takes one working day. Setup starts from $500, and recurring cloud storage costs for a 50GB workload average $20/month. With block-level deduplication, you can reduce storage costs by up to 90%.
Get a consultation — we’ll assess your infrastructure and propose a solution. Proven track record: 100% restoration success in our projects.







