不建议在生产环境用 docker compose 部署 mysql 集群作为唯一高可用方案,但可用于中小规模且有运维兜底能力的场景;关键需配置 binlog、唯一 server-id、独立 volume、自定义 network,并手动初始化复制用户与 change master to,持续监控 seconds_behind_master 和复制线程状态。

直接说结论:不建议在生产环境用 Docker Compose 部署 MySQL 集群作为唯一高可用方案,但可以用于中小规模、有明确运维兜底能力的场景;关键在于配置加固、网络隔离、数据持久化和复制链路可验证。
docker-compose.yml 是编排起点,不是终点。真实生产里出问题的从来不是“起不来”,而是“跑着跑着就不同步”或“重启后主从断开”。
MySQL 主从必须显式配置 binlog 和 server-id
只靠 MYSQL_ROOT_PASSWORD 启动的容器默认不开启 binlog,server-id 也默认为 0 —— 这两个值是主从复制的硬性前提,缺一不可。
-
server-id必须全局唯一(主库设为 1,从库分别设为 2、3…),且不能动态修改,改了要重启 MySQL 实例 -
log-bin必须指定文件名(如mysql-bin),不能只写log-bin=ON,否则 MySQL 8.0+ 会拒绝启动 -
binlog-format=ROW是推荐值,语句级(STATEMENT)在某些函数或非确定性操作下会同步失败 - 生产建议加
sync-binlog=1和innodb_flush_log_at_trx_commit=1,牺牲一点性能换数据不丢
docker-compose.yml 中 volumes 和 networks 要严格分离
常见错误是把主从共用一个 volume,或者没定义自定义 network,导致容器间 DNS 解析失败、端口冲突或数据混写。
- 每个实例必须挂载独立的
data目录(如./master-data:/var/lib/mysql),否则重启后数据状态错乱 - 必须用
networks块声明 bridge 网络(如mysql-net),并让主从都接入,不能依赖默认网络 —— 默认网络重启后 IP 可能变,CHANGE MASTER TO里的 host 就失效 - 从库
depends_on只控制启动顺序,不保证主库 MySQL 服务已就绪;实际初始化需靠脚本轮询mysqladmin ping或延迟等待 - 避免使用
host.docker.internal:它在 Linux 上默认不可用,跨平台不一致
主从关系必须手动创建复制用户并执行 CHANGE MASTER TO
Docker Compose 启动后,MySQL 实例只是“活着”,不代表主从链路已建立。自动初始化只做数据库/用户创建,不做复制配置。
- 进主库执行:
CREATE USER 'repl'@'%' IDENTIFIED BY 'strong-repl-pass'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES; - 进从库执行前,先
SHOW MASTER STATUS记下File和Position;再运行CHANGE MASTER TO MASTER_HOST='mysql-master', MASTER_USER='repl', MASTER_PASSWORD='strong-repl-pass', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=157; -
MASTER_HOST必须填 service name(如mysql-master),不是localhost或 IP —— 容器内 localhost 指自己 - 启动复制:
START SLAVE;,然后SHOW SLAVE STATUS\G看Seconds_Behind_Master和两个Yes(Slave_IO_Running&Slave_SQL_Running)
生产必须监控复制延迟和错误,不能只看容器状态
docker-compose ps 显示 “Up” 只代表容器进程在跑,不代表 MySQL 复制正常。很多线上事故都是因为 Seconds_Behind_Master 悄悄涨到几小时才被发现。
- 从库
SHOW SLAVE STATUS中Seconds_Behind_Master: NULL表示 I/O 或 SQL 线程挂了,不是“零延迟” - 常见卡点:
Got fatal error 1236(主库 binlog 被清理)、Error_code: 1062(主键冲突)、Relay log read failure(磁盘满或权限问题) - 建议在从库加健康检查:
mysql -h mysql-slave -u root -prootpass -e "SELECT @@read_only, (SELECT Seconds_Behind_Master FROM performance_schema.replication_slave_status)" - 不要跳过错误(
SET GLOBAL sql_slave_skip_counter = 1)除非你清楚后果;优先查日志、重搭 relay log 或重建从库
真正麻烦的从来不是“怎么搭起来”,而是“怎么确保它一直对”。主从复制的脆弱性藏在时序、日志生命周期、网络抖动和人为误操作里。哪怕用了 docker-compose up -d,也要把它当传统 MySQL 一样盯住 SHOW SLAVE STATUS 和错误日志。











