最轻量可控的MySQL自动备份方式是docker exec调用mysqldump配合cron,但必须解决密码安全、时区统一、权限配置及一致性参数四大关键问题。

直接用 docker exec 调 mysqldump 配合 cron 是最轻量、最可控的自动备份方式,无需额外容器或服务,但必须处理好密码安全、时区和权限三处关键问题。
为什么不用 mysqldump 容器单独跑备份?
单独起一个临时容器执行 mysqldump 看似“解耦”,实际引入额外复杂度:需配置网络连通性(尤其是自定义 bridge 网络)、MySQL 认证方式(host 限制、SSL)、以及临时容器内时区/语言环境不一致导致的 $(date) 错乱。而 docker exec 直接复用原容器环境,避免了这些隐性故障点。
常见错误现象:ERROR 1045 (28000): Access denied for user 'root'@'172.18.0.3'——这是因新容器 IP 不在 MySQL user 表 host 白名单中;或 mysqldump: Got error: 2003: Can't connect to MySQL server——网络未打通。
- 始终优先使用
docker exec mysql-container mysqldump ...,而非docker run --network=... mysql:8.0 mysqldump ... - 确认 MySQL 容器内
user表中 root 的 host 是%或具体宿主机/bridge 网络段,不是localhost - 若必须用独立容器,改用
--network container:mysql-container共享网络命名空间,绕过 host 白名单校验
密码不能写在命令行里,但也不能全靠交互
把密码明文塞进 -p'xxx' 会被 ps aux 或 shell 历史记录捕获,生产环境禁止。但每次 docker exec 交互输密码又无法自动化。
正确做法是利用 MySQL 客户端配置文件 ~/.my.cnf,由 mysqldump 自动读取:
[client] user = root password = your_strong_password host = localhost
注意三点:
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- 该文件必须挂载进容器内部(如启动容器时加
-v /host/my.cnf:/root/.my.cnf:ro),且权限为600,否则mysqldump拒绝读取 - 容器内路径要匹配:官方镜像默认读
/root/.my.cnf,Alpine 镜像可能读/home/mysql/.my.cnf,需docker exec mysql-container ls -l /root/.my.cnf确认 - 宿主机上创建该文件后,立即执行
chmod 600 /host/my.cnf,否则备份脚本会静默失败
crontab 时间不准?先查容器和宿主机时区是否一致
脚本里 $(date +%F) 输出的是宿主机时间,但若 MySQL 容器内时区是 UTC,而你按北京时间设置 0 2 * * *(凌晨2点),结果备份文件名是昨天的日期,日志也对不上。
检查并统一时区:
- 宿主机执行:
timedatectl | grep "Time zone" - 容器内执行:
docker exec mysql-container date - 若不一致,启动容器时加
-e TZ=Asia/Shanghai(或对应时区),或挂载宿主机/etc/localtime:-v /etc/localtime:/etc/localtime:ro - crontab 条目本身不依赖容器时区,它只按宿主机 cron daemon 的系统时间触发
备份脚本里最容易漏掉的三个参数
只写 mysqldump -u root -p database 能跑通,但线上库一出事就恢复不了。这三个参数不是可选,是保命项:
-
--single-transaction:InnoDB 表必备,保证备份期间写入不阻塞,且导出是一致性快照;MyISAM 表必须换--lock-all-tables -
--routines --triggers --events:缺一不可。存储过程、触发器、事件调度器不会被默认导出,恢复后功能缺失很难排查 -
--default-character-set=utf8mb4:防止 emoji 或四字节字符乱码,尤其当表字符集是utf8mb4_unicode_ci时
完整推荐命令片段:
docker exec mysql-container mysqldump \ -u root \ --single-transaction \ --routines \ --triggers \ --events \ --default-character-set=utf8mb4 \ myapp_db | gzip > /backup/myapp_db-$(date +%F).sql.gz
真正麻烦的从来不是“怎么写完脚本”,而是“怎么让脚本在下周、下个月、换人维护时依然稳定输出可恢复的备份”。时区、密码载体、一致性参数、文件权限——这四点漏掉任何一项,备份就只是自我安慰。










