A Docker container setup for backing up Docker volumes from specific containers using BorgBackup.
Developed for OpsBay - Personal Ops Stack
- π Encrypted backups using Borg's repokey-blake2 encryption
- π― Target specific containers by name
- π¦ Automatically discovers and backs up all volumes mounted on target containers
- ποΈ LZ4 compression for fast backups
- π Automatic pruning with configurable retention policy
- π³ Minimal Alpine-based image
- Docker installed
- Access to
/var/run/docker.sock(to inspect containers) - Access to
/var/lib/docker/volumes(to read volume data)
A ready-to-use Docker image is available at Docker Hub:
docker pull itefixnet/docker-volume-backup-borg:latest-
Clone or create the project directory
-
Create environment file
cp .env.example .env
-
Configure environment variables in
.env:BORG_PASSPHRASE=your-secure-passphrase-here BORG_REPO=ssh://user@backup-server.example.com/path/to/borg-repo BACKUP_CONTAINERS=container1,container2,container3 STOP_CONTAINERS=postgres,mysql TZ=UTC
-
Build the container
docker build -t docker-volume-backup-borg . -
Setup SSH keys for remote backup (if using SSH repository)
# Generate SSH key if you don't have one ssh-keygen -t ed25519 -f ~/.ssh/borg_backup_key # Copy public key to backup server ssh-copy-id -i ~/.ssh/borg_backup_key.pub user@backup-server.example.com
-
Run a backup
Using default SSH keys from
~/.ssh:docker run --rm \ --env-file .env \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \ -v ~/.ssh:/root/.ssh:ro \ docker-volume-backup-borgOr with a specific SSH key:
docker run --rm \ --env-file .env \ -e BORG_RSH="ssh -i /root/.ssh/borg_backup_key" \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \ -v ~/.ssh/borg_backup_key:/root/.ssh/borg_backup_key:ro \ docker-volume-backup-borg
Note: The Docker socket is mounted read-write (not
:ro) to allow stopping/starting containers whenSTOP_CONTAINERSis set.
| Variable | Required | Default | Description |
|---|---|---|---|
BORG_PASSPHRASE |
Yes | - | Passphrase for encrypting the Borg repository |
BORG_REPO |
Yes | - | Borg repository location (SSH URL or local path) |
BORG_RSH |
No | ssh |
SSH command to use (set to ssh -i /root/.ssh/keyname for specific key) |
BACKUP_CONTAINERS |
Yes | - | Comma-separated list of container names to backup |
STOP_CONTAINERS |
No | - | Comma-separated list of containers to stop before backup (leave empty for none) |
KEEP_DAILY |
No | 7 |
Number of daily backups to keep |
KEEP_WEEKLY |
No | 4 |
Number of weekly backups to keep |
KEEP_MONTHLY |
No | 6 |
Number of monthly backups to keep |
TZ |
No | UTC |
Timezone for backup timestamps |
The following volumes are mounted in the container:
/var/run/docker.sock- Docker socket to inspect and optionally stop/start containers/var/lib/docker/volumes- Docker volumes directory (read-only) to access volume data~/.ssh- SSH keys (read-only) for authentication to remote Borg repository
Run a one-time backup:
docker run --rm \
--env-file .env \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \
-v ~/.ssh:/root/.ssh:ro \
docker-volume-backup-borg backupNote: backup is the default command and can be omitted.
For applications where consistency is critical (databases, etc.), specify which containers to stop during backup:
docker run --rm \
-e STOP_CONTAINERS=postgres,mysql \
--env-file .env \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \
-v ~/.ssh:/root/.ssh:ro \
docker-volume-backup-borgEach specified container will be stopped immediately before backing up its volumes, then restarted right after. This minimizes downtime - containers are only down for their own backup duration, not the entire backup run. If an error occurs, containers are automatically restarted via cleanup trap. Other containers in BACKUP_CONTAINERS will continue running throughout.
Add a cron job on your host system:
# Edit crontab
crontab -e
# Add entry (daily backup at 2 AM)
0 2 * * * cd /path/to/docker-volume-backup-borg && docker run --rm --env-file .env -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/docker/volumes:/var/lib/docker/volumes:ro -v ~/.ssh:/root/.ssh:ro docker-volume-backup-borg >> backup.log 2>&1List all archives in the repository:
docker run --rm \
--env-file .env \
-v ~/.ssh:/root/.ssh:ro \
docker-volume-backup-borg listList contents of a specific archive:
docker run --rm \
--env-file .env \
-v ~/.ssh:/root/.ssh:ro \
docker-volume-backup-borg list ARCHIVE_NAMEShow repository statistics:
docker run --rm \
--env-file .env \
-v ~/.ssh:/root/.ssh:ro \
docker-volume-backup-borg infoShow specific archive info:
docker run --rm \
--env-file .env \
-v ~/.ssh:/root/.ssh:ro \
docker-volume-backup-borg info ARCHIVE_NAME-
List available backups:
docker run --rm \ --env-file .env \ -v ~/.ssh:/root/.ssh:ro \ docker-volume-backup-borg list -
Extract a backup to current directory:
docker run --rm \ --env-file .env \ -v ~/.ssh:/root/.ssh:ro \ -v $(pwd):/restore \ -w /restore \ docker-volume-backup-borg \ extract ARCHIVE_NAME
-
Or mount and explore:
docker run --rm -it \ --env-file .env \ --cap-add SYS_ADMIN \ --device /dev/fuse \ -v ~/.ssh:/root/.ssh:ro \ docker-volume-backup-borg \ borg mount $BORG_REPO /mnt
- The backup script connects to the Docker daemon via the Docker socket
- For each specified container:
- If listed in
STOP_CONTAINERS, stops the container for consistency - Discovers all mounted volumes
- Backs up each volume using Borg with compression and encryption
- Prunes old backups for each volume independently based on retention policy
- Restarts the container immediately (minimizing downtime)
- If listed in
- Compacts the repository to reclaim space
- Any containers not restarted due to errors are automatically restarted via cleanup trap
Backups are stored on the remote server specified in BORG_REPO. The Borg repository will be initialized automatically on the first run.
Important:
- Keep your
BORG_PASSPHRASEsafe! Without it, you cannot restore your backups. - Ensure your SSH keys have proper permissions (
chmod 600 ~/.ssh/borg_backup_key) - For local backups, use
BORG_REPO=/backups/borg-repoand mount-v ./borg-repo:/backups/borg-repo
- The container needs access to Docker socket and volumes directory (privileged access)
- Run on trusted systems only
- Protect the
.envfile (contains passphrase) - Consider storing the Borg repository on a separate disk or remote location
- Regularly test backup restoration
Ensure the container has access to /var/lib/docker/volumes. You may need to run with appropriate privileges or adjust volume mount paths based on your Docker installation.
On some systems, Docker volumes may be stored in a different location. Update the volume mount path in your docker run command accordingly (e.g., -v /path/to/volumes:/var/lib/docker/volumes:ro).
Verify container names with:
docker ps --format "{{.Names}}"You can modify backup.sh to:
- Stop containers before backup (for consistency)
- Send notifications on backup completion
- Upload backups to remote storage
- Add pre/post-backup hooks
To use a local repository instead of remote:
-
Update
BORG_REPOin.env:BORG_REPO=/backups/borg-repo
-
Mount local directory instead of SSH keys:
docker run --rm \ --env-file .env \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /var/lib/docker/volumes:/var/lib/docker/volumes:ro \ -v ./borg-repo:/backups/borg-repo \ docker-volume-backup-borg
BSD 2-Clause License - See LICENSE file for details.
Developed for OpsBay - Personal Ops Stack.