A persistent docker volume retains the data for your container. This can be backed up and restored via scripts
Locate a volume for backup
List your volumes
docker volume ls
I want to back up this one
local opc_postgres_data
You can list the volume’s contents here
docker run --rm -v opc_postgres_data:/data busybox ls -la /data
total 64 drwx------ 19 999 999 4096 Dec 20 16:26 . drwxr-xr-x 1 root root 18 Dec 20 16:28 .. -rw------- 1 999 999 3 Dec 20 16:22 PG_VERSION drwx------ 6 999 999 46 Dec 20 16:22 base drwx------ 2 999 999 4096 Dec 20 16:25 global drwx------ 2 999 999 6 Dec 20 16:22 pg_commit_ts drwx------ 2 999 999 6 Dec 20 16:22 pg_dynshmem -rw------- 1 999 999 5743 Dec 20 16:22 pg_hba.conf
Backing up
Create a new file named
volume-backup.sh
nano volume-backup.sh
Paste the following content and ctrl+x to save - changing the
VOLUME_NAME
#!/bin/bash # Volume to Backup VOLUME_NAME="opc_postgres_data" # Set the current date for the backup file BACKUP_DATE=$(date +"%Y%m%d_%H%M%S") # Define the backup directory BACKUP_DIR="/home/opc/backups" # Create a backup of the Docker container data docker run --rm -v $VOLUME_NAME:/data -v $BACKUP_DIR:/backup busybox sh -c "cd /data && tar czf /backup/${VOLUME_NAME}_backup_${BACKUP_DATE}.tar.gz ." echo "Backup completed: $BACKUP_DIR/${VOLUME_NAME}_backup_${BACKUP_DATE}.tar.gz"
Make a backups folder
mkdir backups
Make the script executable
chmod +x volume-backup.sh
STRONGLY ADVISED: Stop your container before backup
Run the backup script
./volume-backup.sh
View the contents of the backup
tar -tvf $BACKUP_DIR/$VOLUME_NAME_backup_$BACKUP_DATE.tar.gz
drwx------ 999/999 0 2024-12-20 09:22 data/ drwx------ 999/999 0 2024-12-19 15:29 data/pg_wal/ drwx------ 999/999 0 2024-12-19 13:16 data/pg_wal/archive_status/ -rw------- 999/999 16777216 2024-12-20 09:52 data/pg_wal/000000010000000000000001 -rw------- 999/999 16777216 2024-12-19 15:29 data/pg_wal/000000010000000000000002 drwx------ 999/999 0 2024-12-20 09:23 data/global/
You can now restart your container
Restoring
Make a file called
volume-restore.sh
nano volume-restore.sh
Paste in the following Ctrl+x to save - changing the
VOLUME_NAME
andBACKUP_FILE
#!/bin/bash # Volume to restore VOLUME_NAME="opc_postgres_data" # Backup file to restore from (replace with your actual backup file name) BACKUP_FILE="/home/opc/backups/opc_postgres_data_backup_20241220_164111.tar.gz" # Restore the Docker volume from the backup docker run --rm -v $VOLUME_NAME:/data -v $(dirname $BACKUP_FILE):/backup busybox sh -c "rm -rf /data/* /data/..?* /data/.[!.]*; tar xzf /backup/$(basename $BACKUP_FILE) -C /data" echo "Restore completed for volume: $VOLUME_NAME"
Make the script executable
chmod +x volume-restore.sh
Run the script
./volume-restore.sh
Check if it restored OK
docker run --rm -v opc_postgres_data:/data busybox ls -la /data
total 64 drwx------ 19 999 999 4096 Dec 20 16:26 . drwxr-xr-x 1 root root 18 Dec 20 16:28 .. -rw------- 1 999 999 3 Dec 20 16:22 PG_VERSION drwx------ 6 999 999 46 Dec 20 16:22 base drwx------ 2 999 999 4096 Dec 20 16:25 global drwx------ 2 999 999 6 Dec 20 16:22 pg_commit_ts drwx------ 2 999 999 6 Dec 20 16:22 pg_dynshmem -rw------- 1 999 999 5743 Dec 20 16:22 pg_hba.conf
Testing
I added the the user added-after-backup
to my volume managed by my postgresSQL container. Note: I already took a backup before this point.
I then…
Stop my containers (i.e my docker-compose)
Run the
volume-restore.sh
scriptStart the containers
When its restored, the new user (and all changes since the backup) are gone
Schedule Daily Backups
Now lets hook this up to backup every day
Edit crontab
export EDITOR=nano; crontab -e
Paste this on the last line to run it daily
0 0 * * * /bin/bash /home/opc/volume-backup.sh
CTRL+X to save the file and exit
You’ll then get daily backups on the stroke of midnight
-rw-r--r--. 1 root root 8602367 Dec 21 00:00 opc_postgres_data_backup_20241221_000001.tar.gz
ENJOY
What’s the picture? It’s The Majestic, Leeds, which caught fire 10 years ago.
Blog Credits: Avinash Bendigeri