A comprehensive Bash script for automating backups of MariaDB, MySQL, and PostgreSQL databases running in Docker containers. Features automatic compression, retention management, and detailed logging.
Find a file
2026-02-19 12:34:13 +08:00
mariadb.conf.d First version for testing 2026-02-04 23:39:22 +08:00
.gitignore Added verbose option so that if successful there is no output 2026-02-16 13:52:01 +08:00
docker_db_backup.sh Now pass MySQL and MariaDB password as environment variable to prevent warning when passed on command line 2026-02-19 12:34:13 +08:00
LICENSE Added license and updated and corrected readme to include new version command line flag 2026-02-05 00:12:22 +08:00
README.md Added verbose option so that if successful there is no output 2026-02-16 13:52:01 +08:00

Docker Database Backup

A comprehensive Bash script for automating backups of MariaDB, MySQL, and PostgreSQL databases running in Docker containers. Features automatic compression, retention management, and detailed logging.

Features

  • Multi-Database Support: Backup MariaDB, MySQL, and PostgreSQL databases
  • Docker Integration: Uses docker exec to run backup commands in containers
  • Automatic Compression: Optional gzip compression of backup files (enabled by default)
  • Retention Management: Automatically removes old backups based on configurable retention policy
  • Session-Based Organization: Groups backups and logs by timestamp in subdirectories
  • Comprehensive Logging: Timestamped console and file logging to track all backup activities
  • Comprehensive Logging: Timestamped file logging for each session; console output is only shown when --verbose is specified or when an error occurs
  • Dry-Run Mode: Test backups without actually executing Docker commands
  • Flexible CLI Options: Override retention, specify backup directory, and enable dry-run mode
  • Flexible CLI Options: Override retention, specify backup directory, enable dry-run mode, and enable verbose logging with --verbose
  • Error Handling: Robust error handling with detailed error reporting

⚠️ Disclaimer

This script is provided as-is without any guarantees. Use at your own risk.

You MUST validate that backups are being created correctly and that data can be successfully restored before relying on this script for critical data. I cannot guarantee the correctness or integrity of backups created by this script. Always maintain multiple backup strategies and regularly test restore procedures to ensure your data is protected.

Directory Structure

docker-db-backup/
├── docker_db_backup.sh      # Main backup script
├── README.md                # This file
├── mariadb.conf.d/          # MariaDB database configurations
│   └── example.conf
├── mysql.conf.d/            # MySQL database configurations
│   └── example.conf
├── postgres.conf.d/         # PostgreSQL database configurations
│   └── example.conf
└── backups/                 # Backup output directory (user-specified)
    ├── 20260204_232306/
    │   ├── testdb.sql.gz
    │   └── backup.log
    └── 20260204_232307/
        ├── testdb.sql.gz
        └── backup.log

Installation

  1. Clone or download the script to your desired location
  2. Make the script executable:
    chmod +x docker_db_backup.sh
    

Configuration

Database Configuration Files

Create .conf files in the appropriate subdirectory (mariadb.conf.d/, mysql.conf.d/, or postgres.conf.d/) for each database you want to backup.

Each configuration file must define these variables:

# Docker container name running the database
DB_CONTAINER="my_mariadb_container"

# Database user for authentication
DB_USER="backup_user"

# Database password
DB_PASSWORD="secure_password"

# Database name to backup
DB_NAME="my_database"

# Prefix for backup filename (extension will be appended automatically)
DB_BACKUP_FILE_PREFIX="my_database"

Example Configurations

MariaDB Example (mariadb.conf.d/production.conf):

DB_CONTAINER="mariadb_prod"
DB_USER="root"
DB_PASSWORD="root_password"
DB_NAME="production_db"
DB_BACKUP_FILE_PREFIX="production_db"

MySQL Example (mysql.conf.d/staging.conf):

DB_CONTAINER="mysql_staging"
DB_USER="backup"
DB_PASSWORD="backup_pass"
DB_NAME="staging_db"
DB_BACKUP_FILE_PREFIX="staging_db"

PostgreSQL Example (postgres.conf.d/analytics.conf):

DB_CONTAINER="postgres_analytics"
DB_USER="postgres"
DB_PASSWORD="postgres_password"
DB_NAME="analytics"
DB_BACKUP_FILE_PREFIX="analytics"

Usage

Basic Backup

./docker_db_backup.sh --backup-dir ./backups

This will:

  1. Find all .conf files in mariadb.conf.d/, mysql.conf.d/, and postgres.conf.d/
  2. Backup each configured database
  3. Compress backups with gzip (default)
  4. Keep the last 10 backup sessions (default)
  5. Create a timestamped subdirectory in ./backups/ with all files from this run

Quick Examples

# Basic backup
./docker_db_backup.sh --backup-dir ./backups

# Dry-run (no Docker execution)
./docker_db_backup.sh --dry-run --backup-dir ./backups

# Verbose (print live logs to console)
./docker_db_backup.sh --verbose --backup-dir ./backups
# short form for verbose
./docker_db_backup.sh -v --backup-dir ./backups

# Use short form for backup directory
./docker_db_backup.sh -d /mnt/backups

# Show version (long and short)
./docker_db_backup.sh --version
./docker_db_backup.sh -V

# View help
./docker_db_backup.sh --help

Backup to Specific Directory

./docker_db_backup.sh --backup-dir /mnt/backups

Or use the short form:

./docker_db_backup.sh -d /mnt/backups

Test Backups (Dry-Run Mode)

Test the script without actually executing Docker commands:

./docker_db_backup.sh --dry-run --backup-dir ./backups

Output will show what would be backed up without creating the actual Docker connections.

Override Retention Policy

Keep only the 5 most recent backup sessions:

./docker_db_backup.sh --backup-dir ./backups --max-backups 5

Or use the = syntax:

./docker_db_backup.sh --backup-dir ./backups --max-backups=5

Combine Options

./docker_db_backup.sh --dry-run --backup-dir ./backups --max-backups 3

This will:

  • Run in dry-run mode (no Docker execution)
  • Use ./backups as output directory
  • Keep only 3 most recent sessions

View Help

./docker_db_backup.sh --help

Display Version

Show the script name and version (short and long forms are supported):

./docker_db_backup.sh --version
# or (short form)
./docker_db_backup.sh -V

Example output:

docker_db_backup.sh 0.1.0

Verbose Output

Print live logs to the console while the script runs (otherwise logs are only written to the session backup.log). Also note that on error the script will dump the session log to stderr so failures are visible even when not running verbose.

./docker_db_backup.sh --verbose --backup-dir ./backups
# or short form
./docker_db_backup.sh -v --backup-dir ./backups

Environment Variables

You can also set configuration via environment variables:

# Enable/disable compression (default: true)
COMPRESS_BACKUPS=false ./docker_db_backup.sh --backup-dir ./backups

# Set retention policy (default: 10)
MAX_BACKUPS=7 ./docker_db_backup.sh --backup-dir ./backups

Note: CLI flags take precedence over environment variables.

Output Files

Each backup run creates a timestamped session directory containing:

  • Backup Files: {DB_BACKUP_FILE_PREFIX}.sql.gz (or .sql if compression disabled)
  • Log File: backup.log with detailed backup operation logs

Example directory structure after 3 backups:

backups/
├── 20260204_232306/
│   ├── production_db.sql.gz
│   ├── staging_db.sql.gz
│   └── backup.log
├── 20260204_232307/
│   ├── production_db.sql.gz
│   ├── staging_db.sql.gz
│   └── backup.log
└── 20260204_232308/
    ├── production_db.sql.gz
    ├── staging_db.sql.gz
    └── backup.log

Automatic Cleanup

The script automatically manages disk usage by:

  1. Creating timestamped session directories (YYYYMMDD_HHMMSS format)
  2. Keeping the MAX_BACKUPS most recent session directories
  3. Removing older session directories entirely (including all files)

For example, with --max-backups 2, the script will keep only the 2 newest session directories and delete older ones.

Log Files

Each backup session creates a backup.log file in the session directory with timestamped entries:

[2026-02-04 23:23:06] [INFO] Script: docker_db_backup.sh Version: 0.1.0
[2026-02-04 23:23:06] [INFO] Session: 20260204_232306 Directory: /opt/db-backup/backup
s/20260204_232306
[2026-02-04 23:23:06] [INFO] Starting database backup process...
[2026-02-04 23:23:06] [INFO] Maximum backups per database: 3
[2026-02-04 23:23:06] [INFO] Processing MariaDB databases...
[2026-02-04 23:23:06] [INFO] Starting MariaDB backup for: production_db
[2026-02-04 23:23:06] [SUCCESS] MariaDB backup completed: /backups/20260204_232306/production_db.sql.gz
[2026-02-04 23:23:06] [INFO] Cleaning up old backup sessions...
[2026-02-04 23:23:06] [INFO] Backup Summary:
[2026-02-04 23:23:06] [INFO]   Total: 1
[2026-02-04 23:23:06] [INFO]   Successful: 1
[2026-02-04 23:23:06] [INFO]   Failed: 0

Scheduling with Cron

Schedule daily backups at 2 AM:

0 2 * * * /path/to/docker-db-backup/docker_db_backup.sh --backup-dir /mnt/backups >> /var/log/db-backups.log 2>&1

Or with retention management (keep 30 days of daily backups):

0 2 * * * /path/to/docker-db-backup/docker_db_backup.sh --backup-dir /mnt/backups --max-backups 30 >> /var/log/db-backups.log 2>&1

Backup Strategy Recommendations

Daily Backups (Keep 14 Days)

0 2 * * * /path/to/docker-db-backup/docker_db_backup.sh --backup-dir /backups/daily --max-backups 14

Weekly Backups (Keep 12 Weeks)

0 3 * * 0 /path/to/docker-db-backup/docker_db_backup.sh --backup-dir /backups/weekly --max-backups 12

Monthly Backups (Keep 24 Months)

0 4 1 * * /path/to/docker-db-backup/docker_db_backup.sh --backup-dir /backups/monthly --max-backups 24

Compression

By default, backups are compressed with gzip to save disk space. To disable compression:

COMPRESS_BACKUPS=false ./docker_db_backup.sh --backup-dir ./backups

Compressed files: database.sql.gz Uncompressed files: database.sql

Error Handling

The script includes comprehensive error handling:

  • Missing Configuration: Reports missing required variables
  • Docker Connection Failures: Logs specific errors and continues with other databases
  • File Permission Issues: Handles backup directory creation and permissions
  • Invalid CLI Arguments: Clear error messages for incorrect flags

Exit code 1 is returned if any backup fails.

Requirements

  • Bash 4.0+ (uses set -euo pipefail)
  • Docker CLI: Must be installed and have access to database containers
  • Database Tools:
    • mariadb-dump (for MariaDB backups)
    • mysqldump (for MySQL backups)
    • pg_dump (for PostgreSQL backups)
  • Standard Tools: find, grep, sed, awk, date

Troubleshooting

Docker Connection Errors

Ensure the Docker container names in your .conf files are correct:

docker ps --filter "name=container_name"

Permission Denied

Ensure you have write permissions to the backup directory:

mkdir -p ./backups && chmod 755 ./backups

Backup File Not Created

Check the log file for details:

cat backups/YYYYMMDD_HHMMSS/backup.log

Compression Issues

If gzip is unavailable, disable compression:

COMPRESS_BACKUPS=false ./docker_db_backup.sh --backup-dir ./backups

License

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
                    Version 2, December 2004

 Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>

 Everyone is permitted to copy and distribute verbatim or modified
 copies of this license document, and changing it is allowed as long
 as the name is changed.

            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. You just DO WHAT THE FUCK YOU WANT TO.

Support

For issues, questions, or improvements, refer to the script comments and log files for debugging information. If that doesn't help then create an new issue!