Docker Compose Backups with Restic and S3-Compatible Storage
Immutable backups sound tidy on paper. In practice, the useful bit is keeping a backup somewhere that is hard to tamper with, then checking that it still restores.
Why immutable backups matter for Docker Compose
For Docker Compose setups, the point is straightforward: keep data safe from accidental deletion and from anything that gets into the host with write access. An immutable backup cannot be changed or deleted in place, which gives you a better chance of recovering when something goes wrong.
S3-compatible storage fits this model well. Backblaze B2 or MinIO can be used as the storage layer, so the backup is not sitting on the same machine as the container stack. That matters more than clever wording about compliance.
There are trade-offs. Object storage is not a magic shield, and it still needs access control, retention settings, and regular checks. If you never test a restore, you only have a hopeful copy of your data.
Restic in a Docker Compose stack
Restic works with S3-compatible storage and is simple enough to run in a container of its own. A basic Compose service looks like this:
version: '3'
services:
restic:
image: restic/restic
environment:
- RESTIC_REPOSITORY=s3:s3.amazonaws.com/mybucket
- RESTIC_PASSWORD=mysecretpassword
volumes:
- ./backups:/backups
That points Restic at an S3 bucket and mounts the local data to back up. From there, the job can be run manually or scheduled. The setup is plain, which is usually a good sign.
Checking backup integrity
Verification is the part people skip until they need it. Restic has built-in verification tools, so after a backup you can run a check against the repository and look for corruption or mismatches.
Running that on a schedule is sensible. A cron job against the S3 storage gives you a regular check that the backup is still readable, rather than assuming the upload was enough.
Rotation and retention
Backup rotation keeps storage under control. The usual approach is to keep several versions, then prune older ones so the repository does not grow without limit.
The 3-2-1 rule still makes sense here: three copies of the data, on two different media types, with one copy offsite. With Docker Compose, that can mean more than one Restic job if you want separate backup targets.
Restic can prune old snapshots, which trims the repository while keeping the recent history you still need.
restic prune
Cron containers for automation
A cron container is a blunt but workable way to run backups on a schedule. The example below runs Restic every hour:
cron:
image: alpine
volumes:
- ./backups:/backups
entrypoint: /bin/sh -c

