基于 Docker Compose 的 MySQL 8.0 数据库备份恢复方案,使用 Percona-XtraBackup 进行全量和增量备份,支持 S3 兼容对象存储(如 MinIO),并提供时间点恢复(PITR)功能。
创建 .env 文件或直接在 docker-compose.yml 中配置环境变量:
services:
mysql:
environment:
# MySQL 配置
MYSQL_ROOT_PASSWORD: your_root_password
MYSQL_DATABASE: your_database
# S3 兼容对象存储配置(MinIO 示例)
S3_BACKUP_ENABLED: true
S3_ENDPOINT: minio.example.com:9000
S3_ACCESS_KEY: your_access_key
S3_SECRET_KEY: your_secret_key
S3_BUCKET: mysql-backups
S3_REGION: us-east-1
S3_USE_SSL: false
S3_FORCE_PATH_STYLE: true
# 备份配置
FULL_BACKUP_SCHEDULE: "0 2 * * 0" # 每周日凌晨 2 点
INCREMENTAL_BACKUP_SCHEDULE: "0 3 * * *" # 每天凌晨 3 点
BACKUP_RETENTION_DAYS: 30
# 钉钉机器人通知配置(可选)
DINGTALK_WEBHOOK_ENABLED: false
# DINGTALK_WEBHOOK_URL: https://oapi.dingtalk.com/robot/send?access_token=your_token
docker-compose up -d
# 查看容器状态
docker-compose ps
# 查看日志
docker-compose logs -f mysql
# 查看备份日志
docker-compose exec mysql tail -f /backups/backup.log
通过 Cron 定时任务自动执行备份,无需手动干预。
在 docker-compose.yml 中配置:
environment:
# 全量备份计划(Cron 格式:分钟 小时 日 月 星期)
FULL_BACKUP_SCHEDULE: "0 2 * * 0" # 每周日凌晨 2 点
INCREMENTAL_BACKUP_SCHEDULE: "0 3 * * *" # 每天凌晨 3 点
Cron 格式说明:分钟 小时 日 月 星期
常用示例:
0 2 * * 0 - 每周日凌晨 2 点0 3 * * * - 每天凌晨 3 点0 */6 * * * - 每 6 小时0 2 1 * * - 每月 1 日凌晨 2 点修改 docker-compose.yml 后重启服务:
docker-compose restart mysql
方式 A:使用统一入口(推荐)
docker-compose exec mysql python3 /scripts/main.py backup full
方式 B:直接调用 Python 脚本
docker-compose exec mysql python3 /scripts/tasks/backup/full_backup.py
方式 A:使用统一入口(推荐)
docker-compose exec mysql python3 /scripts/main.py backup incremental
方式 B:直接调用 Python 脚本
docker-compose exec mysql python3 /scripts/tasks/backup/incremental_backup.py
注意:增量备份需要先有全量备份作为基础。
# 查看本地备份文件
docker-compose exec mysql ls -lh /backups/full/
docker-compose exec mysql ls -lh /backups/incremental/
# 查看 S3 中的备份(如果启用了 S3)
docker-compose exec mysql mc ls s3/mysql-backups/full/
docker-compose exec mysql mc ls s3/mysql-backups/incremental/
# 查看备份日志
docker-compose exec mysql tail -n 100 /backups/backup.log
恢复到指定备份的时间点状态。
docker-compose stop mysql
方式 A:使用统一入口(推荐)
# 恢复指定时间戳的全量备份(自动从 S3 下载,如果启用)
docker-compose run --rm mysql python3 /scripts/main.py restore backup 20251127_020000
# 恢复全量备份并应用增量备份
docker-compose run --rm mysql python3 /scripts/main.py restore backup 20251127_020000 backup_20251128_030000.tar.gz backup_20251129_030000.tar.gz
方式 B:直接调用 Python 脚本
# 恢复指定时间戳的全量备份(自动从 S3 下载,如果启用)
docker-compose run --rm mysql python3 /scripts/tasks/restore/restore_backup.py 20251127_020000
# 恢复全量备份并应用增量备份
docker-compose run --rm mysql python3 /scripts/tasks/restore/restore_backup.py 20251127_020000 backup_20251128_030000.tar.gz backup_20251129_030000.tar.gz
说明:
恢复脚本会下载并准备好备份,但不会自动应用到数据目录。需要手动应用:
# 使用统一入口
docker-compose run --rm mysql python3 /scripts/main.py restore apply /backups/restore
# 或直接调用 Python 脚本
docker-compose run --rm mysql python3 /scripts/tasks/restore/apply_restore.py /backups/restore
环境变量选项:
USE_MOVE_BACK=true - 使用 --move-back(恢复后删除恢复目录中的备份)BACKUP_EXISTING_DATA=false - 不备份现有数据docker-compose start mysql
恢复到任意指定的时间点,而不仅仅是备份的时间点。需要二进制日志(binlog)支持。
docker-compose stop mysql
方式 A:使用统一入口(推荐)
# 恢复到指定时间点(自动查找备份和二进制日志)
docker-compose run --rm \
-e RESTORE_TZ="Asia/Shanghai" \
mysql python3 /scripts/main.py restore pitr "2025-11-27 18:23:10"
# 指定全量备份时间戳
docker-compose run --rm \
-e RESTORE_TZ="Asia/Shanghai" \
mysql python3 /scripts/main.py restore pitr "2025-11-27 18:23:10" 20251127_020000
# 指定全量备份和增量备份
docker-compose run --rm \
-e RESTORE_TZ="Asia/Shanghai" \
mysql python3 /scripts/main.py restore pitr "2025-11-27 18:23:10" 20251127_020000 backup_20251127_030000.tar.gz
方式 B:直接调用 Python 脚本
# 恢复到指定时间点(自动查找备份和二进制日志)
docker-compose run --rm \
-e RESTORE_TZ="Asia/Shanghai" \
mysql python3 /scripts/tasks/restore/point_in_time_restore.py "2025-11-27 18:23:10"
# 指定全量备份时间戳
docker-compose run --rm \
-e RESTORE_TZ="Asia/Shanghai" \
mysql python3 /scripts/tasks/restore/point_in_time_restore.py "2025-11-27 18:23:10" 20251127_020000
时间格式说明:
YYYY-MM-DD HH:MM:SSRESTORE_TZ 环境变量修改)"2025-11-27 18:23:10"详细说明请参考:时间格式使用说明
说明:
docker-compose start mysql
# 连接数据库检查数据
docker-compose exec mysql mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SELECT COUNT(*) FROM your_table;"
| 参数 | 说明 | 示例 |
|---|---|---|
MYSQL_ROOT_PASSWORD | MySQL root 用户密码 | your_root_password |
MYSQL_DATABASE | 默认数据库名 | your_database |
MYSQL_USER | 默认数据库用户 | your_user |
MYSQL_PASSWORD | 默认数据库用户密码 | your_password |
如果希望使用专门的备份用户(推荐),可以配置:
| 参数 | 说明 | 示例 |
|---|---|---|
MYSQL_BACKUP_USER | 备份专用用户 | backup_user |
MYSQL_BACKUP_PASSWORD | 备份专用用户密码 | backup_password |
备份用户所需权限:
RELOADPROCESSLOCK TABLESREPLICATION CLIENTBACKUP_ADMIN如果未设置,将依次使用 MYSQL_USER 或 root 用户。
| 参数 | 说明 | 必填 | 示例 |
|---|---|---|---|
S3_BACKUP_ENABLED | 是否启用 S3 备份 | 是 | true / false |
S3_ENDPOINT | S3 服务端点地址 | 是 | minio.example.com:9000 |
S3_ACCESS_KEY | 访问密钥 ID | 是 | your_access_key |
S3_SECRET_KEY | 访问密钥 | 是 | your_secret_key |
S3_BUCKET | 存储桶名称 | 是 | mysql-backups |
S3_REGION | 区域(MinIO 通常使用 us-east-1) | 是 | us-east-1 |
S3_USE_SSL | 是否使用 SSL/TLS | 否 | true / false(MinIO 通常为 false) |
S3_FORCE_PATH_STYLE | 是否使用路径样式访问 | 否 | true(MinIO 需要设置为 true) |
S3_ALIAS | S3 别名(用于 MinIO 客户端) | 否 | s3(默认值) |
environment:
S3_BACKUP_ENABLED: true
S3_ENDPOINT: 192.168.1.100:9000
S3_ACCESS_KEY: minioadmin
S3_SECRET_KEY: minioadmin
S3_BUCKET: mysql-backups
S3_REGION: us-east-1
S3_USE_SSL: false
S3_FORCE_PATH_STYLE: true
S3_ALIAS: s3
如果只需要本地备份,可以关闭 S3 备份:
environment:
S3_BACKUP_ENABLED: false
当 S3_BACKUP_ENABLED=false 时:
./backups/| 参数 | 说明 | 格式 | 默认值 |
|---|---|---|---|
FULL_BACKUP_SCHEDULE | 全量备份 Cron 计划 | 分钟 小时 日 月 星期 | 0 2 * * 0(每周日凌晨 2 点) |
INCREMENTAL_BACKUP_SCHEDULE | 增量备份 Cron 计划 | 分钟 小时 日 月 星期 | 0 3 * * *(每天凌晨 3 点) |
BACKUP_RETENTION_DAYS | 备份保留天数 | 数字 | 30 |
LOCAL_BACKUP_RETENTION_HOURS | 本地备份保留时间(小时) | 数字 | 0(上传到 S3 后立即删除) |
注意:LOCAL_BACKUP_RETENTION_HOURS 仅在 S3_BACKUP_ENABLED=true 时生效。当 S3_BACKUP_ENABLED=false 时,本地备份将永久保留。
| 参数 | 说明 | 必填 | 示例 |
|---|---|---|---|
DINGTALK_WEBHOOK_ENABLED | 是否启用钉钉通知 | 是 | true / false |
DINGTALK_WEBHOOK_URL | 钉钉机器人 Webhook URL | 是(当启用时) | https://oapi.dingtalk.com/robot/send?access_token=your_token |
environment:
# 启用钉钉通知
DINGTALK_WEBHOOK_ENABLED: true
# 钉钉机器人 Webhook URL
DINGTALK_WEBHOOK_URL: https://oapi.dingtalk.com/robot/send?access_token=your_access_token
DINGTALK_WEBHOOK_URL 环境变量启用钉钉通知后,备份成功或失败时都会自动发送通知:
备份成功通知包含:
备份失败通知包含:
| 参数 | 说明 | 默认值 |
|---|---|---|
BACKUP_BASE_DIR | 备份基础目录 | /backups |
RESTORE_TZ | 恢复时使用的时区(PITR) | Asia/Shanghai |
mysql/
├── docker-compose.yml # Docker Compose 配置文件
├── Dockerfile # MySQL 镜像构建文件
├── docker-entrypoint.sh # 容器入口点脚本
├── mysql_data/ # MySQL 数据目录(自动创建)
├── mysql_config/ # MySQL 配置文件目录(自动创建)
└── backups/ # 备份文件目录(自动创建)
├── full/ # 全量备份目录
│ └── YYYYMMDD_HHMMSS/ # 按时间戳组织的备份
├── incremental/ # 增量备份目录
│ └── YYYYMMDD_HHMMSS/ # 按时间戳组织的备份
├── binlog_backup_*/ # 二进制日志备份(PITR 使用)
└── backup.log # 备份日志文件
./backups/
├── full/
│ └── 20251127_020000/ # 全量备份时间戳目录
│ └── backup.tar.gz # 备份压缩文件
├── incremental/
│ └── 20251128_030000/ # 增量备份时间戳目录
│ └── backup.tar.gz # 备份压缩文件
└── backup.log # 备份日志
s3://mysql-backups/
├── full/
│ ├── backup_20251127_020000.tar.gz
│ └── backup_20251128_020000.tar.gz
├── incremental/
│ ├── backup_20251128_030000.tar.gz
│ └── backup_20251129_030000.tar.gz
└── .metadata/
├── latest_full_backup_timestamp.txt
└── latest_incremental_backup_timestamp.txt
# 查看容器状态
docker-compose ps
# 查看备份日志
docker-compose exec mysql tail -n 100 /backups/backup.log
# 查看最近的备份
docker-compose exec mysql ls -lht /backups/full/ | head -5
docker-compose exec mysql ls -lht /backups/incremental/ | head -5
# 列出全量备份
docker-compose exec mysql mc ls s3/mysql-backups/full/
# 列出增量备份
docker-compose exec mysql mc ls s3/mysql-backups/incremental/
# 检查备份文件大小
docker-compose exec mysql mc ls -lh s3/mysql-backups/full/
# 手动清理旧备份(根据 BACKUP_RETENTION_DAYS 配置)
# 使用统一入口(推荐)
docker-compose exec mysql python3 /scripts/main.py backup cleanup
# 或直接调用 Python 脚本
docker-compose exec mysql python3 /scripts/tasks/backup/cleanup_old_backups.py
检查 MySQL 连接:
docker-compose exec mysql mysql -h 127.0.0.1 -u root -p"${MYSQL_ROOT_PASSWORD}" -e "SELECT 1"
检查 S3 连接(如果启用了 S3):
docker-compose exec mysql mc alias list
docker-compose exec mysql mc ls s3/mysql-backups/
查看详细日志:
docker-compose logs mysql | grep -i backup
docker-compose exec mysql tail -n 200 /backups/backup.log
如果增量备份提示找不到基础备份:
手动执行一次全量备份:
# 使用统一入口(推荐)
docker-compose exec mysql python3 /scripts/main.py backup full
# 或直接调用 Python 脚本
docker-compose exec mysql python3 /scripts/tasks/backup/full_backup.py
检查基础备份文件:
docker-compose exec mysql cat /backups/LATEST_FULL_BACKUP
检查 cron 服务状态:
docker-compose exec mysql service cron status
查看 cron 任务列表:
docker-compose exec mysql crontab -l
手动测试备份脚本:
# 使用统一入口(推荐)
docker-compose exec mysql python3 /scripts/main.py backup full
# 或直接调用 Python 脚本
docker-compose exec mysql python3 /scripts/tasks/backup/full_backup.py
检查备份文件是否存在:
docker-compose exec mysql ls -lh /backups/full/
检查 MySQL 是否已停止(恢复前必须停止):
docker-compose ps mysql
查看恢复日志:
docker-compose logs mysql | grep -i restore
MYSQL_BACKUP_USER 和 MYSQL_BACKUP_PASSWORD,使用最小权限原则本项目仅供学习和参考使用。
Content type
Image
Digest
sha256:05b77d316…
Size
185.8 MB
Last updated
8 months ago
docker pull zziaguan/mysql:8.0.35