Automated Docker Container Storage Backups
I run several containers in my home lab and the missing piece to my puzzle has been backups. That is to say I have no backup strategy. In my spare time, I've been working out how to backup the container storage and I feel pretty satisfied with my current solution.
Prerequisites
I keep all my container persistent data in a folder on my host machine in the format of /docker/{service-name}
so /docker/caddy
for instance. Therefore, only this folder should be backed up as it's the hardest to recreate.
Some of my containers use SQLLite or other databases. Copying the persistent data while the container is running could cause corruption. So, stopping and starting the container is necessary.
Finally, I want maximum flexibility so I want to be able to just copy the data in the filesystem.
rclone
Rclone is an application that allows you to mount cloud storage as a logical drive and perform I/O operations against it. Since I am a Microsoft 365 subscriber, I chose to use OneDrive.
Flask Server
I wanted to have a container that would perform actions based on either RESTful command or cronjobs. So I created flask-cron-server which will spin up a Flask server at port 2128
. The
From there I was able to create server.py
. This is the file that runs the Flask server and is executed on container startup:
It reads in a JSON file called /app/config/containers.json
that defines all the containers along with the folder that should be archived and where that archive should be stored.
The call to backup is executed in a separate thread and a 202 Accepted
response is sent to the caller to let them know that the command was received, but it is unknown how long it will take.
Finally, the whole thing is driven by a simple JSON
[
{
"container_name": "caddy",
"source_folder": "/source/caddy",
"destination_folder": "/destination/caddy",
"retention_days": 7
},
{
"container_name": "freshrss",
"source_folder": "/source/freshrss",
"destination_folder": "/destination/freshrss",
"retention_days": 7
},
{
"container_name": "guacamole",
"source_folder": "/source/guacamole",
"destination_folder": "/destination/guacamole",
"retention_days": 7
},
{
"container_name": "mosquitto",
"source_folder": "/source/mosquitto",
"destination_folder": "/destination/mosquitto",
"retention_days": 7
},
{
"container_name": "ps5-mqtt",
"source_folder": "/source/ps5-mqtt",
"destination_folder": "/destination/ps5-mqtt",
"retention_days": 7
},
{
"container_name": "slash",
"source_folder": "/source/slash",
"destination_folder": "/destination/slash",
"retention_days": 7
},
{
"container_name": "write-freely",
"source_folder": "/source/writefreely",
"destination_folder": "/destination/writefreely",
"retention_days": 7
},
{
"container_name": "homeassistant",
"source_folder": "/source/ha",
"destination_folder": "/destination/ha",
"retention_days": 14
}
]
Docker Container
The final step was to create the Docker container and stack
services:
container-backup:
image: zackwag/flask-container-backup:latest
container_name: container-backup
restart: unless-stopped
ports:
- 2128:2128
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /docker/container-backup/config:/app/config
- /docker:/source
- onedrive-backup:/destination
environment:
- PYTHONUNBUFFERED=1
- TZ=America/New_York
volumes:
onedrive-backup:
driver: rclone
driver_opts:
remote: onedrive:backup
allow_other: "true"
vfs-cache-mode: writes
networks: {}
I'm in the timezone of New York, so you will need to change it to where you live.
Also, I made sure to include /var/run/docker.sock:/var/run/docker.sock:ro
so that I could start and stop containers.
Finally, I followed the directions for Docker Volume Plugin
. This allowed me to create the volume onedrive-backup
that points to the /backup
folder in OneDrive.
`
Calling Backups
Now that the container is running I can simply call
curl -X POST [IP ADDRESS]:2128/backup
to backup all the containers specified in containers.json
or just
curl -X POST {IP ADDRESS}:2128/backup/{container name}
To backup a specific container specified in containers.json
.
I have setup automations that daily in Home Assistant, that call the main /backup
endpoint to kick off backups.