This note is about how to use offen/docker-volume-backup (GitHub, Documentation) to back up (and restore) docker volumes. Offen works with mounted folders as well as docker volumes and offers many backup targets.
I solved it by running the container with --privileged
Manual backup
Into current folder
Letβs say we want to back up the volume volumename into an archive file thatβs placed inside our current directory.
Set shell variable with volume name, useful if you want to backup multiple volumes (different syntax on Windows?)
DVAR='volumename'
Make sure the corresponding containers are stopped. If the volume you want to backup contains a database, it might be advisable to create a database backup inside this volume now.
Create the backup file. It will be named like volumename-2024-05-23T11-45-02.tar.gz.
I use this approach on remote hosts to create backups inside a volume (offen_backup_syncthing) thatβs mounted to a Syncthing container, which copies the backups to my home (or another backup location).
Required folder structure
The folder offenbackup inside the volume offen_backup_syncthing must be present, the copy script inside offen/docker-volume-backup fails otherwise. Workaround: β replace BACKUP_ARCHIVE="/archive/offenbackup" with BACKUP_ARCHIVE="/archive", which changes where the backup archives are stored inside the volume offen_backup_syncthing.
The contents of offen_backup_syncthing are structured like this to separate the backup archives from the syncthing files (.stfolder & .stversions):
Make sure the corresponding containers are stopped. If the volume you want to backup contains a database, it might be advisable to create a database backup inside this volume now.
The backup gets stored as a .tar.gz file, which can be extracted with tar -xvf backup.tar.gz. This creates a new folder backup (Note: NOT with the name of the archive, but with the name of the highest folder inside it!) and within this a folder with the volume name. The volumeβs contents are inside this folder.
You can also view the content of backup.tar.gz like this:
tar -tvf backup.tar.gz
or using Docker (if for some reason tar is not installed):
docker run --rm -v ./backup.tar.gz:/data/backup.tar.gz alpine tar -tvf /data/backup.tar.gz
Restore a backup manually
Assumptions:
In your working directory is only one backup file per volume (so $DVAR-*.tar.gz is unambiguous).
Your archive file created by offen/docker-volume-backup has its contents nested like in this example (the volumeβs name, $DVAR, is here βvolumenameβ):
# tar -tvf backup.tar.gz
tar: Removing leading `/' from member names
drwxr-xr-x root/root 0 2024-05-23 13:45 /backup
drwxr-xr-x 1000/users 0 2024-05-23 13:38 /backup/volumename
-rw-r--r-- 1000/users 4 2024-05-23 13:15 /backup/volumename/config.json
With local extraction (docker cp)
Warning
Depending on your working directory, you might run into problems related to the filesystemβs path length limit.
Set shell variable with the name of the volume you want to restore to
DVAR='volumename'
Remove old volume contents (after stopping related containers!)
Rename the backup archive that you want to restore to backup.tar.gz. cp because we might want to archive the backup file.
This step is necessary because Docker wonβt accept -v ./$DVAR-*.tar.gz:/archive/backup.tar.gz:ro, instead Docker creates a new folder called volumename-*.tar.gz.
cp $DVAR-*.tar.gz backup.tar.gz
Restore the backup. Without the flag--strip-components=2 the contents of our restored volume would look like this: /backup/$DVAR/[contents of original volume] instead of [contents of original volume]. Depending on how youβve nested the leading folders in your backup, you might have to change this. You can inspect your backup file first with tar -tvf backup.tar.gz.
docker run --rm -v $DVAR:/target -v ./backup.tar.gz:/archive/backup.tar.gz:ro alpine tar --strip-components=2 -C /target -xzvf /archive/backup.tar.gz
Cleanup
rm backup.tar.gz
Personal backup scripts
This section is about my personal backup scripts, adapted to the layout of my systems.