Sign inSign up

onesystems/dockerbackup

By onesystems

Updated about 1 month ago

Backup container for systems that need to have the database and file system backed up

Image
Security
Web servers
Databases & storage
1

100K+

onesystems/dockerbackup repository overview

Docker Backup Container

A minimal Alpine-based container to back up directories and databases on a schedule, with notification support via Nextcloud Talk Bot and e-mail.

Runs as non-root (uid 1000), uses supercronic, supports Docker secrets (*_FILE), optional age encryption, and a status-file healthcheck.


Features

  • File backups (tar.gz, optional .age)
  • PostgreSQL, MariaDB and MySQL backups (.sql.gz, optional .age)
  • Cron-based scheduling via supercronic
  • Optional backup on container start (RUN_ON_START=on)
  • Retention-based cleanup
  • Talk Bot notifications (HMAC-based)
  • Optional e-mail notifications via SMTP
  • Stale lockfile cleanup (after 1 hour)
  • Unified logging (file + stderr)
  • Custom container/service labeling for notifications

Environment Variables

General
VariableDescriptionDefault
FILES_TO_BACKUPSpace-separated list of folders to back up/data
BACKUP_DIRRoot folder for all backups/backup
LOG_DIRLog file location/logs
RETENTION_DAYSDays to keep old backups30
CRON_SCHEDULECron expression (5 fields)falls back to BACKUP_INTERVAL
BACKUP_INTERVALLegacy alias for CRON_SCHEDULE0 * * * *
RUN_ON_STARTRun one backup before starting cronoff
STACK_NAMELogical stack name
BACKUP_NAMEFriendly container/service namehostname
Encryption (optional)
VariableDescription
BACKUP_ENCRYPT=onEncrypt each artifact with age
BACKUP_AGE_RECIPIENTage recipient (age1...)
BACKUP_AGE_RECIPIENT_FILERead recipient from file (Docker secret)

Decrypt later with your private key: age -d -i key.txt backup.tar.gz.age > backup.tar.gz

Secrets (*_FILE)

Any of these can be provided as a file instead of a plain env value:

  • POSTGRES_PASSWORD_FILE
  • MARIADB_PASSWORD_FILE
  • MYSQL_PASSWORD_FILE
  • SMTP_PASS_FILE
  • NC_TALK_BOT_SECRET_FILE
  • BACKUP_AGE_RECIPIENT_FILE
Database (optional)

Set DB_TYPE=postgres, mariadb, mysql, or none

PostgreSQL
VariableDescription
POSTGRES_HOSTDatabase host
POSTGRES_PORTPort (default 5432)
POSTGRES_USERUsername
POSTGRES_PASSWORD / _FILEPassword
POSTGRES_DATABASEDB name
POSTGRES_EXTRA_OPTSExtra pg_dump flags (validated)
MariaDB
VariableDescription
MARIADB_HOSTDatabase host
MARIADB_PORTPort (default 3306)
MARIADB_USERUsername
MARIADB_PASSWORD / _FILEPassword
MARIADB_DATABASEDB name
MARIADB_EXTRA_OPTSExtra dump flags (validated)
MySQL
VariableDescription
MYSQL_HOSTDatabase host
MYSQL_PORTPort (default 3306)
MYSQL_USERUsername
MYSQL_PASSWORD / _FILEPassword
MYSQL_DATABASEDB name
MYSQL_EXTRA_OPTSExtra dump flags (validated)
Nextcloud Talk Bot (HMAC)
VariableDescription
NC_TALK_NOTIFY=onEnable Talk Bot notifications
NC_TALK_URLNextcloud base URL
NC_TALK_BOT_CHANNELBot ID or room token
NC_TALK_BOT_SECRET / _FILEShared secret
Email Notifications (optional)
VariableDescription
EMAIL_NOTIFY=onEnable e-mail alerts
EMAIL_TORecipient
EMAIL_FROMSender
SMTP_SERVERSMTP hostname/IP
SMTP_PORTPort (default 587)
SMTP_USERSMTP user (if auth needed)
SMTP_PASS / _FILESMTP password
SMTP_TLS=onEnable TLS (default on)

SMTP config is written only when EMAIL_NOTIFY=on.

Healthcheck
VariableDescriptionDefault
BACKUP_STATUS_FILESuccess marker path/backup/.last_success
HEALTHCHECK_MAX_AGE_SECONDSMax age of a successful marker90000 (~25h)
HEALTHCHECK_INITIAL_GRACE_SECONDSAfter start, stay healthy without a fresh marker while waiting for cron (supercronic must be PID 1)93600 (~26h)

The healthcheck is healthy when:

  1. .last_success exists and is newer than HEALTHCHECK_MAX_AGE_SECONDS, or
  2. there is no fresh success yet, but the container uptime is still within HEALTHCHECK_INITIAL_GRACE_SECONDS and supercronic is running

That way Swarm/Compose do not restart-loop on deploy when RUN_ON_START=off and the next run is only at the cron time (e.g. midnight). After the grace period without any successful backup, the check becomes unhealthy.

Recommended start_period for the Docker healthcheck: a few minutes (startup only), not the full wait until cron.


Example docker-compose.yml

services:
  backup:
    image: onesystems/dockerbackup:latest
    user: "1000:1000"
    read_only: true
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    tmpfs:
      - /tmp:size=256m,mode=1777
      - /home/backup/config:size=1m,uid=1000,gid=1000,mode=0700
    environment:
      FILES_TO_BACKUP: "/data"
      BACKUP_DIR: "/backup"
      LOG_DIR: "/logs"
      RETENTION_DAYS: 30
      CRON_SCHEDULE: "0 * * * *"
      BACKUP_NAME: "web-backup-db"
      DB_TYPE: "postgres"
      POSTGRES_HOST: "postgres"
      POSTGRES_USER: "backupuser"
      POSTGRES_PASSWORD_FILE: "/run/secrets/postgres_password"
      POSTGRES_DATABASE: "myapp"
      BACKUP_ENCRYPT: "on"
      BACKUP_AGE_RECIPIENT_FILE: "/run/secrets/age_recipient"
    secrets:
      - postgres_password
      - age_recipient
    volumes:
      - ./data:/data:ro
      - ./backup:/backup
      - ./logs:/logs
    healthcheck:
      test: ["CMD", "/scripts/healthcheck.sh"]
      interval: 5m
      timeout: 10s
      retries: 3
      start_period: 2m

secrets:
  postgres_password:
    file: ./secrets/postgres_password
  age_recipient:
    file: ./secrets/age_recipient

Ensure host dirs for /backup and /logs are writable by UID/GID 1000.


Folder Structure

/backup/
  .last_success
  2025-04/
    files_data_2025-04-30_1400.tar.gz[.age]
    postgres_myapp_2025-04-30_1400.sql.gz[.age]
/logs/
  backup_2025-04-30.log

Cleanup

Backups older than RETENTION_DAYS are removed automatically. Log entries show deleted files.


Healthcheck

The backup script writes /backup/.last_success only on a fully successful run.

  • With a fresh marker → healthy
  • Without (or with a stale marker), within HEALTHCHECK_INITIAL_GRACE_SECONDS after start and while supercronic runs → still healthy (waiting for cron)
  • After that grace without success → unhealthy

No RUN_ON_START required for Swarm/Compose stability.


Author


License

MIT License – free for commercial and private use.

Tag summary

Content type

Image

Digest

sha256:6aec9b1b8

Size

30.9 MB

Last updated

about 1 month ago

docker pull onesystems/dockerbackup