Docker MySQL 自动备份与恢复教程(systemd 定时任务)

发布时间:2026/6/27 2:59:10
Docker MySQL 自动备份与恢复教程(systemd 定时任务) Docker MySQL 自动备份与恢复教程systemd 定时任务本文介绍如何为 Docker 中运行的 MySQL 数据库建立自动备份方案使用mysqldump导出数据库自动压缩为.sql.gz每 5 天备份一次自动保留最近 30 天的备份使用systemd timer设置开机自动启用提供完整的数据库恢复流程。本文统一使用MyProject作为示例项目代号。实际使用时只需要替换项目名称、容器名、数据库名、密码和目录即可。1. 需要替换的配置请根据自己的服务器环境修改以下名称示例名称说明MyProject项目名称或项目代号myproject项目名称的小写形式myproject-mysqlMySQL Docker 容器名称myproject-backend后端 Docker 容器名称myproject123456MySQL root 密码/root/MyProject_Backup/mysql备份保存目录/root/backup_myproject_mysql.sh自动备份脚本路径先查看正在运行的 Docker 容器dockerps--formattable {{.Names}}\t{{.Status}}输出示例NAMES STATUS myproject-mysql Up 10 days myproject-backend Up 10 days2. 为什么不要直接复制 MySQL 数据目录MySQL 数据通常挂载在宿主机目录中例如/root/MyProject_Web/data/mysql/不要在 MySQL 正在运行时直接复制这个目录cp-a/root/MyProject_Web/data/mysql /root/mysql_backup因为 MySQL 在运行过程中会持续写入表数据、日志和索引文件。直接复制可能产生不一致的数据副本恢复时可能失败。更可靠的方法是使用mysqldump将数据库导出为 SQL 文件再压缩为.sql.gz这种备份方式可以在 MySQL 正常运行时执行且更容易迁移、检查和恢复。3. 创建独立备份目录建议将备份保存在项目目录之外避免项目目录被误删时连备份一起丢失。mkdir-p/root/MyProject_Backup/mysqlchmod700/root/MyProject_Backup/mysql以后生成的备份文件会保存在/root/MyProject_Backup/mysql/文件名示例myproject_2026-06-26_200000.sql.gz4. 创建 MySQL 自动备份脚本创建脚本文件vi/root/backup_myproject_mysql.sh将下面内容完整粘贴进去#!/usr/bin/env bashset-euopipefail# # MyProject Docker MySQL 自动备份脚本# # Docker 中 MySQL 容器名称CONTAINER_NAMEmyproject-mysql# 要备份的数据库名称DATABASE_NAMEmyproject# MySQL root 密码MYSQL_ROOT_PASSWORDmyproject123456# 备份保存目录BACKUP_DIR/root/MyProject_Backup/mysql# 保留最近多少天的备份# 每 5 天备份一次保留 30 天约等于保留 6 份RETENTION_DAYS30# 创建备份目录mkdir-p${BACKUP_DIR}chmod700${BACKUP_DIR}# 检查 MySQL 容器是否正在运行if!dockerps--format{{.Names}}|grep-qx${CONTAINER_NAME};thenecho[$(date%F %T)] 错误MySQL 容器${CONTAINER_NAME}未运行。2exit1fi# 生成带时间戳的备份文件名TIMESTAMP$(date%F_%H%M%S)BACKUP_FILE${BACKUP_DIR}/${DATABASE_NAME}_${TIMESTAMP}.sql.gzTMP_FILE${BACKUP_FILE}.tmpecho[$(date%F %T)] 开始备份数据库${DATABASE_NAME}# 导出数据库并进行 gzip 压缩# --single-transactionInnoDB 数据库可在不停机状态下进行一致性备份# --quick减少大数据库备份时的内存占用dockerexec\-eMYSQL_PWD${MYSQL_ROOT_PASSWORD}\${CONTAINER_NAME}\mysqldump\-uroot\--single-transaction\--quick\--routines\--events\--triggers\--databases${DATABASE_NAME}\|gzip-c${TMP_FILE}# 检查压缩包是否完整gzip-t${TMP_FILE}# 验证成功后将临时文件改为正式备份文件mv${TMP_FILE}${BACKUP_FILE}echo[$(date%F %T)] 备份成功${BACKUP_FILE}# 删除超过保留期限的旧备份find${BACKUP_DIR}\-typef\-name*.sql.gz\-mtime${RETENTION_DAYS}\-deleteecho[$(date%F %T)] 已清理超过${RETENTION_DAYS}天的旧备份。保存并退出vi按 Esc 输入 :wq 按 Enter为脚本添加执行权限chmod700/root/backup_myproject_mysql.sh检查权限ls-l/root/backup_myproject_mysql.sh正常应看到类似-rwx------ 1 root root ... /root/backup_myproject_mysql.sh其中x表示脚本具有执行权限。5. 手动测试备份先手动运行一次脚本确认配置正确/root/backup_myproject_mysql.sh正常情况下会输出类似[2026-06-26 20:00:00] 开始备份数据库myproject [2026-06-26 20:00:01] 备份成功/root/MyProject_Backup/mysql/myproject_2026-06-26_200000.sql.gz [2026-06-26 20:00:01] 已清理超过 30 天的旧备份。查看备份文件ls-lh/root/MyProject_Backup/mysql/正常会看到myproject_2026-06-26_200000.sql.gz建议先确认手动备份成功再配置自动定时任务。6. 创建 systemd 服务创建service文件cat/etc/systemd/system/myproject-mysql-backup.serviceEOF [Unit] DescriptionMyProject MySQL Backup Afterdocker.service Requiresdocker.service [Service] Typeoneshot ExecStart/root/backup_myproject_mysql.sh EOF查看服务文件cat/etc/systemd/system/myproject-mysql-backup.service正常应显示[Unit] DescriptionMyProject MySQL Backup Afterdocker.service Requiresdocker.service [Service] Typeoneshot ExecStart/root/backup_myproject_mysql.sh7. 创建每 5 天执行一次的 systemd 定时器创建 timer 文件cat/etc/systemd/system/myproject-mysql-backup.timerEOF [Unit] DescriptionRun MyProject MySQL backup every 5 days [Timer] # 定时器启动后每隔 5 天执行一次 OnUnitActiveSec5d # 服务器关机期间错过任务时恢复运行后补做 Persistenttrue [Install] WantedBytimers.target EOF参数说明OnUnitActiveSec5d表示定时器启动后每隔 5 天运行一次备份服务。Persistenttrue表示若服务器在计划执行时关机系统恢复后会补做错过的备份任务。8. 启用定时器并设置开机自动启动执行systemctl daemon-reload systemctlenable--nowmyproject-mysql-backup.timer systemctl restart myproject-mysql-backup.timer检查定时器状态systemctl status myproject-mysql-backup.timer正常会显示类似Loaded: loaded (...; enabled; ...) Active: active (waiting) Trigger: ...其中enabled服务器重启后定时器会自动启动active (waiting)定时器正在等待下一次执行Trigger下一次自动备份的时间。查看下次运行时间systemctl list-timers--all|grepmyproject-mysql-backup检查是否已设置为开机启动systemctl is-enabled myproject-mysql-backup.timer正常应输出enabled9. 测试 systemd 是否能正常调用备份脚本手动触发一次 systemd 备份systemctl start myproject-mysql-backup.service查看日志journalctl-umyproject-mysql-backup.service-n30--no-pager正常会看到类似Starting MyProject MySQL Backup... 开始备份数据库myproject 备份成功/root/MyProject_Backup/mysql/myproject_2026-06-26_200000.sql.gz 已清理超过 30 天的旧备份。 Finished MyProject MySQL Backup.这说明 systemd 可以正常调用备份脚本。10. 常用备份管理命令查看所有备份文件ls-lh/root/MyProject_Backup/mysql/手动立即备份/root/backup_myproject_mysql.sh或systemctl start myproject-mysql-backup.service查看自动备份状态systemctl status myproject-mysql-backup.timer查看下一次备份时间systemctl list-timers--all|grepmyproject-mysql-backup查看备份日志journalctl-umyproject-mysql-backup.service-n50--no-pager停止自动备份systemctl disable--nowmyproject-mysql-backup.timer重新启用自动备份systemctlenable--nowmyproject-mysql-backup.timer11. 如何恢复某一份数据库备份假设需要恢复以下备份/root/MyProject_Backup/mysql/myproject_2026-06-26_200000.sql.gz恢复会将当前数据库替换为历史备份版本。开始前请确认选中的备份文件正确。11.1 先备份当前数据库恢复前先生成一份当前数据库备份/root/backup_myproject_mysql.sh这样即使恢复了错误版本也可以回退到恢复操作前的状态。11.2 停止项目后端容器先查看运行中的容器dockerps假设后端容器名称为myproject-backend停止后端dockerstop myproject-backendmyproject-backend是示例名称请替换为实际后端容器名称。MySQL 容器myproject-mysql不需要停止。11.3 删除当前数据库dockerexec-it\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot-eDROP DATABASE IF EXISTS myproject;这条命令会删除当前的myproject数据库因此必须确认前一步的备份已成功完成。11.4 导入指定备份gunzip-c/root/MyProject_Backup/mysql/myproject_2026-06-26_200000.sql.gz\|dockerexec-i\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot导入过程可能没有额外输出只要没有报错一般表示恢复成功。11.5 检查恢复结果查看数据库dockerexec-it\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot-eSHOW DATABASES;查看恢复后的表dockerexec-it\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot-eUSE myproject; SHOW TABLES;能够正常显示表名通常说明恢复成功。11.6 启动后端容器dockerstart myproject-backend将myproject-backend替换成实际后端容器名称。12. 完整恢复流程# 1. 备份恢复前的当前数据库/root/backup_myproject_mysql.sh# 2. 查看所有备份文件确认需要恢复哪一份ls-lh/root/MyProject_Backup/mysql/# 3. 停止项目后端容器dockerstop myproject-backend# 4. 删除当前数据库dockerexec-it\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot-eDROP DATABASE IF EXISTS myproject;# 5. 恢复指定备份gunzip-c/root/MyProject_Backup/mysql/myproject_2026-06-26_200000.sql.gz\|dockerexec-i\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot# 6. 检查恢复后的数据表dockerexec-it\-eMYSQL_PWDmyproject123456\myproject-mysql\mysql-uroot-eUSE myproject; SHOW TABLES;# 7. 启动项目后端容器dockerstart myproject-backend13. 备份策略总结项目设置MySQL 容器myproject-mysql数据库名称myproject备份目录/root/MyProject_Backup/mysql备份脚本/root/backup_myproject_mysql.sh自动备份频率每 5 天一次备份保留时间30 天预计保留份数约 6 份备份格式.sql.gz自动删除旧备份是开机自动启用定时器是14. 进一步建议本文中的备份文件仍然存放在同一台服务器因此可以防止数据库误删错误更新或错误覆盖项目升级失败项目目录被误删数据库表被错误修改。但它无法防止服务器硬盘损坏整台服务器不可用云服务器被删除勒索软件或严重系统故障。对于重要数据库建议定期将以下目录同步到另一块硬盘、NAS、对象存储或另一台服务器/root/MyProject_Backup/mysql/