Automatic restic backup of a docker-compose setup. https://hub.docker.com/r/zettaio/restic-compose-backup
  • Python 98.6%
  • Dockerfile 0.9%
  • Shell 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Michał Krawczyk 143b073ce9
All checks were successful
tests / test (3.13) (push) Successful in 16s
tests / test (3.11) (push) Successful in 18s
tests / lint (push) Successful in 15s
tests / test (3.9) (push) Successful in 17s
Merge pull request #2: Drop SHA tag and package link job
Reviewed-on: ⁨#2
2026-08-13 23:56:54 +02:00
.forgejo/workflows Drop SHA tag and package link job from release workflow 2026-08-13 23:55:06 +02:00
.github Add sponsor 2019-12-11 13:17:32 +01:00
docs Add CLAUDE.md, refresh README and project metadata 2026-08-13 22:59:46 +02:00
extras Bump version 2020-05-28 01:27:06 +02:00
src Add CLAUDE.md, refresh README and project metadata 2026-08-13 22:59:46 +02:00
.gitignore Merge master into dev; fix silent backup failures and modernise deps 2026-08-13 22:20:00 +02:00
.readthedocs.yaml Merge master into dev; fix silent backup failures and modernise deps 2026-08-13 22:20:00 +02:00
CLAUDE.md Add CLAUDE.md, refresh README and project metadata 2026-08-13 22:59:46 +02:00
docker-compose.yaml Merge master into dev; fix silent backup failures and modernise deps 2026-08-13 22:20:00 +02:00
LICENSE Create LICENSE 2019-12-05 00:58:32 +01:00
pytest.ini Fully working tox run 2019-12-05 11:23:33 +01:00
README.md Release on bare version tags and document the published image 2026-08-13 23:33:12 +02:00
restic_compose_backup.env Bump version + bump reqs and base image 2023-03-08 23:09:05 +01:00
swarm-stack.yml Missing label in swarm test file 2020-03-08 17:38:01 +01:00
TODO.md Add CLAUDE.md, refresh README and project metadata 2026-08-13 22:59:46 +02:00
tox.ini Merge master into dev; fix silent backup failures and modernise deps 2026-08-13 22:20:00 +02:00

restic-compose-backup

docs

Backup using restic for a docker-compose setup. Tested with Docker Engine 29.x.

This is a maintained fork of ZettaIO/restic-compose-backup, maintained by Michał Krawczyk. It carries fixes that upstream does not have; see TODO.md and the git history. Please report issues on the Forgejo tracker, not upstream's.

Features:

  • Backs up docker volumes or host binds
  • Backs up postgres, mariadb and mysql databases
  • Notifications over mail/smtp or Discord webhooks

Install

Images are published to the Forgejo container registry on every release tag:

docker pull forgejo.nevy.xyz/nev/restic-compose-backup:latest

For production, pin a release rather than following latest:

docker pull forgejo.nevy.xyz/nev/restic-compose-backup:1.0.0

Every release also publishes a 12 character commit SHA tag, so a deployment can be pinned to one exact build after latest has moved.

To build from source instead:

git clone https://forgejo.nevy.xyz/nev/restic-compose-backup.git
cd restic-compose-backup
docker build -t restic-compose-backup ./src

Database dumps are executed inside the target database container over the docker API, so no mysql/postgres client binaries are needed in this image.

Configuration (env vars)

Minimum configuration

RESTIC_REPOSITORY
RESTIC_PASSWORD

RESTIC_PASSWORD_FILE and RESTIC_PASSWORD_COMMAND are accepted in place of RESTIC_PASSWORD. The container refuses to start if none of them is set.

More config options can be found in the documentation.

Restic backend specific env vars : https://restic.readthedocs.io/en/stable/040_backup.html#environment-variables

Compose Example

We simply control what should be backed up by adding labels to our containers. More details are covered in the documentation.

restic-backup.env

RESTIC_REPOSITORY=<whatever backend restic supports>
RESTIC_PASSWORD=hopefullyasecturepw
# snapshot prune rules
RESTIC_KEEP_DAILY=7
RESTIC_KEEP_WEEKLY=4
RESTIC_KEEP_MONTHLY=12
RESTIC_KEEP_YEARLY=3
# Cron schedule. Run every day at 1am
CRON_SCHEDULE="0 1 * * *"

docker-compose.yaml

services:
  # The backup service
  backup:
    image: forgejo.nevy.xyz/nev/restic-compose-backup:latest
    env_file:
      - restic-backup.env
    volumes:
      # We need to communicate with docker.
      # NOTE: ':ro' only makes the bind mount read-only. It does not restrict
      # the docker API. Anything reaching this socket has root on the host.
      - /var/run/docker.sock:/tmp/docker.sock:ro
      # Persistent storage of restic cache (greatly speeds up all restic operations)
      - cache:/cache
  web:
    image: some_image
    labels:
      # Enables backup of the volumes below
      restic-compose-backup.volumes: true
    volumes:
      - media:/srv/media
      - /srv/files:/srv/files
  mariadb:
    image: mariadb:11.4
    labels:
      # Enables backup of this database
      restic-compose-backup.mariadb: true
    env_file:
      mariadb-credentials.env
    volumes:
      - mariadbdata:/var/lib/mysql
  mysql:
    image: mysql:8.4
    labels:
      # Enables backup of this database
      restic-compose-backup.mysql: true
    env_file:
      mysql-credentials.env
    volumes:
      - mysqldata:/var/lib/mysql

  postgres:
    image: postgres:17
    labels:
      # Enables backup of this database
      restic-compose-backup.postgres: true
    env_file:
      postgres-credentials.env
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  media:
  mysqldata:
  mariadbdata:
  pgdata:
  cache:

The rcb command

Everything is controlled using the rcb command. After configuring backup with labels and restarted the affected services we can quickly view the result using the status subcommand.

$ docker compose run --rm backup rcb status
INFO: Status for compose project 'myproject'
INFO: Repository: '<restic repository>'
INFO: Backup currently running?: False
INFO: Include project name in backup path?: False
INFO: Checking docker availability
INFO: ------------------------- Detected Config -------------------------
INFO: service: web
INFO:  - volume: /var/lib/docker/volumes/myproject_media/_data -> /volumes/web/srv/media
INFO:  - volume: /srv/files -> /volumes/web/srv/files
INFO: service: mysql
INFO:  - mysql (is_ready=True) -> /databases/mysql/all_databases.sql
INFO: service: mariadb
INFO:  - mariadb (is_ready=True) -> /databases/mariadb/all_databases.sql
INFO: service: postgres
INFO:  - postgres (is_ready=True) -> /databases/postgres/mydb.sql
INFO: -------------------------------------------------------------------

The status subcommand lists what will be backed up and even pings the database services checking their availability. The restic command can also be used directly in the container.

rcb backup exits non-zero when the backup fails, so it can be wired into a healthcheck or monitoring alert.

More rcb commands can be found in the documentation.

Running Tests

Requires Python 3.9 or newer. This mirrors what CI runs.

pip install -r src/tests/requirements.txt
pip install ./src
pytest

The package is installed non-editable on purpose: it makes the tests exercise the built artifact, so a packaging mistake fails here rather than in the image.

To run the suite against several interpreters at once, install tox and run it.

Building Docs

pip install -r docs/requirements.txt
sphinx-build docs docs/_build/html

Local dev setup

The git repository contains a simple local setup for development

# Start the compose project
docker compose up -d

docker compose requires the Compose v2 CLI plugin. The standalone docker-compose (v1) reached end of life in 2023 and is not supported.

The swarm stack is optional and only needed when testing SWARM_MODE. It is the only part that needs the overlay network:

# Create an overlay network to link the compose project and stack
docker network create --driver overlay --attachable global
# Deploy the stack
docker stack deploy -c swarm-stack.yml test

In dev we should ideally start the backup container manually

docker compose run --rm backup sh
# pip install the package in the container in editable mode to auto sync changes from host source
pip3 install -e .

Remember to enable swarm mode with docker swarm init/join and disable swarm mode with docker swarm leave --force when needed in development (single node setup).

Contributing

Contributions are welcome regardless of experience level. Don't hesitate submitting issues, opening partial or completed pull requests.


Acknowledgements

This project was created by Einar Forselv and first released in April 2019, with development sponsored by Zetta.IO.

Everything this fork does is built on their design: the label-driven configuration, the restic integration, and the spawned backup container are all their work. This fork exists thanks to them, and is maintained separately only to carry fixes for newer versions of docker, restic and MariaDB. It is not endorsed by or affiliated with Zetta.IO.

Original project: ZettaIO/restic-compose-backup Licensed under the MIT licence, Copyright (c) 2019 Zetta.IO. See LICENSE.

Zetta.IO