Docker stop 默认行为无法保障数据库数据一致性,因其仅等待10秒即发SIGKILL,而PostgreSQL/MySQL关机需完成WAL刷盘、缓冲区同步等操作,耗时远超10秒;应配置stop_grace_period≥60s、使用pg_ctl stop或mysqladmin shutdown主动关闭、结合synchronous_commit=on等存储层防护,并通过日志和启动后校验确认安全关闭。
不能靠 docker stop 默认行为保障数据库数据一致性。它默认只等 10 秒就发 sigkill,而 postgresql 或 mysql 在关闭时需完成 wal 刷盘、缓冲区同步、事务提交等操作,时间远超 10 秒。真正安全的做法是让数据库进程主动响应 sigterm 并完成清理,再由 docker 收尾容器运行时环境。
显式配置停止信号与超时时间
Docker 的 stop_signal 和 stop_grace_period 必须按数据库实际关机耗时设定:
- PostgreSQL 默认监听 SIGTERM,无需改
stop_signal;MySQL 同理,但需确认 mysqld 启动参数未禁用信号处理 -
stop_grace_period建议设为 60s 起:例如 Compose 中写stop_grace_period: 60s,给 checkpoint、flush buffer pool、sync WAL 留出足够窗口 - 避免在健康检查中设置过激的失败阈值,防止停机过程中因探针失败触发自动重启,干扰正常关机流程
计划停机必须绕过 Docker 生命周期
对数据库容器执行计划性维护(如升级、迁移)时,不应直接 docker stop。应先在容器内调用数据库原生命令完成固化:
- PostgreSQL:
docker exec -it db pg_ctl stop -m fast(推荐),确保所有活跃事务结束、WAL 完全刷盘 - MySQL:
docker exec -it db mysqladmin shutdown -u root -p$PASS,比 kill 或 docker kill 更可靠 - 确认容器内数据库进程已退出(
docker exec db ps aux | grep postgres无主进程),再执行docker stop—— 此时只是清理网络命名空间和挂载点,无数据风险
结合数据库与存储层做纵深防护
Docker 本身不解决断电问题,需叠加数据库配置与底层存储能力:
- PostgreSQL 开启强一致性:设置
wal_level = replica+synchronous_commit = on - MySQL 启用双刷:
innodb_flush_log_at_trx_commit = 1+sync_binlog = 1 - 挂载卷使用 ext4/xfs 并启用
barrier=1;确保存储设备支持 PLP(如带电容的 NVMe 或 RAID 卡),防止掉电丢日志 - 禁止用
:z或:ZSELinux 标签挂载数据目录,避免策略延迟导致 sync 失败
验证是否真正安全关闭
仅看容器退出码或状态为 Exited (0) 不代表数据安全。必须检查:
- 容器日志末尾是否有明确 shutdown 标记:PostgreSQL 显示
database system is shut down,MySQL 显示mysqld: Shutdown complete - 下次启动后观察错误日志:若出现
crash recovery、page checksum mismatch或InnoDB: Database page corruption,说明上次关闭不完整 - 必要时做逻辑校验:比如对比关键表行数、检查主从 GTID/LSN 是否连续


















