Skip to content
Hogin Hogin
Go back

Backing Up Docker Containers with Offen

4 мин чтения

In this article we’ll look at how to set up daily backups of Docker volumes, pushing them to S3 storage with notifications via Email and Telegram. We’ll use Offen/docker-volume-backup as our tool.


Sample Docker Compose Configuration

Create a docker-compose.yml file with the following contents:

version: '3.8'

services:
  postgres:
    image: postgres:15
    volumes:
      - pg_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example
    restart: unless-stopped

  backup:
    image: offen/docker-volume-backup:latest
    restart: unless-stopped
    depends_on:
      - postgres
    volumes:
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - pg_data:/backup/pg_data:ro
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      # Schedule configuration (every day at 2:00)
      BACKUP_CRON_EXPRESSION: "0 2 * * *"
      
      # Volumes to back up
      BACKUP_SOURCES: "/backup/pg_data"
      
      # S3 configuration
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
      AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME}
      AWS_ENDPOINT: ${AWS_ENDPOINT}
      
      # Email notifications
      # NOTIFICATION_URLS: "smtp://${SMTP_USERNAME}:${SMTP_PASSWORD}@${SMTP_HOST}:${SMTP_PORT}/?fromAddress=${SMTP_FROM}&toAddresses=${TO_SENT_EMAIL}"
      
      # Telegram notifications
      NOTIFICATION_LEVEL: "info"
      NOTIFICATION_URLS: "telegram://${TELEGRAM_TOKEN}@telegram?chats=${TELEGRAM_USER_ID}"
      
      # Additional settings
      BACKUP_FILENAME: "backup-$(date +%Y-%m-%d).tar.gz"
      BACKUP_RETENTION_DAYS: 7

volumes:
  pg_data:

To store variables securely, use environment variables or a .env file in the same folder as your docker-compose.yaml file.

Example .env file:

SMTP_PORT="465"
SMTP_HOST="smtp.example.com"
SMTP_FROM="noreply@example.com"

SMTP_USERNAME="noreply@example.com""
SMTP_PASSWORD="strongpPassword"

TO_SENT_EMAIL="backups@example.com"

AWS_ACCESS_KEY_ID="asdfjksaghdf"
AWS_SECRET_ACCESS_KEY="sakjdfjkl"
AWS_S3_BUCKET_NAME="docker-backup"
AWS_ENDPOINT="s3.aws.com"

TELEGRAM_TOKEN="sadnljkhjlkf"
TELEGRAM_USER_ID="21341234"

Configuration Explained

1. Application service (PostgreSQL)

2. Backup service


Setting Up Notifications

For Telegram:

  1. Create a bot through @BotFather and get the token.
  2. Find out the chat ID via @userinfobot.
  3. Specify the parameters in the format:
NOTIFICATION_URL="telegram://<YOUR_BOT_TOKEN>@telegram/?chats=<YOUR_CHAT_ID>"

Starting the System

  1. Replace all variables (AWS_SECRET_ACCESS_KEY, TELEGRAM_TOKEN, etc.) with real values.
  2. Run the command:
docker-compose up -d
  1. To test, run a backup manually:
docker-compose exec backup backup

Benefits of This Solution


By using this approach, you’ll protect your Docker applications’ data from loss. Additional settings (for example, backups to multiple storage targets) can be found in the official documentation.

BONUS

Encrypting and Decrypting Backups in Offen/docker-volume-backup

Offen/docker-volume-backup supports end-to-end encryption of backups using the AES-256-GCM algorithm. This protects your data even if the S3 storage is compromised.


1. Setting Up Encryption

Step 1: Generate a key

The key must be a 32-byte string in Base64 or Hex format. Example generation:

# Generate in Base64
openssl rand -base64 32 > backup-key.txt

# Or in Hex
openssl rand -hex 32 > backup-key.txt

Step 2: Add the key to the configuration

In the backup service of the docker-compose.yml file, specify:

environment:
  BACKUP_ENCRYPTION_KEY: "file:/backup-key.txt" # Path inside the container
  # Or directly (not recommended for production):
  # BACKUP_ENCRYPTION_KEY: "your-encryption-key-in-base64-or-hex"

Step 3: Mount the key

Add a volume for the key file:

volumes:
  - ./backup-key.txt:/backup-key.txt:ro

2. How It Works


3. Decrypting Backups

Option 1: Via the docker-volume-backup utility

docker run --rm -v /path/to/backup.tar.gz.gpg:/backup.tar.gz.gpg \
  -v /path/to/backup-key.txt:/backup-key.txt \
  offen/docker-volume-backup:latest decrypt \
  --input /backup.tar.gz.gpg \
  --output /backup.tar.gz \
  --key-file /backup-key.txt

Option 2: Manually with OpenSSL

For a key in Hex format:

openssl enc -d -aes-256-gcm \
  -in backup.tar.gz.gpg \
  -out backup.tar.gz \
  -K "$(cat backup-key.txt)" \
  -iv <(head -c 16 backup.tar.gz.gpg) \
  -aad <(tail -c +17 backup.tar.gz.gpg | head -c 24)

4. Important Considerations

  1. Key storage:
    • Never commit the key to Git
    • Use Docker secrets or a KMS (AWS Secrets Manager, HashiCorp Vault)
    • Rotate keys regularly (but old backups will require the old keys!)
  2. Metadata:
    • File names in S3 are not encrypted
    • For full anonymization, use BACKUP_FILENAME_ENCRYPTED=true

Performance:

Test data: 1 GB
Encryption: ~15 sec (on an Intel i7 CPU)
Decryption: ~12 sec

5. Full Configuration Example

services:
  backup:
    image: offen/docker-volume-backup:latest
    environment:
      BACKUP_ENCRYPTION_KEY: "file:/secrets/backup-key.txt"
      BACKUP_FILENAME_ENCRYPTED: "true" # Random file name
    volumes:
      - ./secrets/backup-key.txt:/secrets/backup-key.txt:ro

6. Recovery Scenarios

If the key is lost:

If the key is compromised:

  1. Generate a new key
  2. Re-encrypt old backups with the new key
  3. Remove the old key from all systems

Recommendations

Encryption in Offen/docker-volume-backup provides enterprise-grade protection with minimal configuration. The key thing is to keep your keys safe!


Share this post:

Previous Post
YubiKey 5
Next Post
MDT Deployment & Administration. Part 4: Bootstrap.ini and CustomSettings.ini