docker compose无法一键完成主从同步,必须配合自定义网络、正确挂载my.cnf(含唯一server-id、row格式binlog/relay-log)、初始化脚本及手动执行start replica验证状态。

docker-compose.yml 本身不支持“一键启动即完成主从同步”,必须配合配置文件、初始化脚本和手动触发 START SLAVE 才能真正跑通。硬要“一键”,只意味着把容器拉起来、配置挂载好、SQL脚本自动执行——但复制链路是否就绪,得看日志和 SHOW SLAVE STATUS\G。
docker-compose.yml 必须暴露的网络与卷映射
主从容器必须在同一个自定义网络里,否则 CHANGE MASTER TO MASTER_HOST='mysql-master' 会解析失败(Docker内部DNS靠服务名通信)。
关键点:
-
networks要显式定义 bridge 网络,不能依赖默认bridge(容器间无法通过服务名互访) -
volumes中配置文件(my.cnf)必须挂载到/etc/mysql/conf.d/或/etc/mysql/my.cnf,MySQL 5.7 默认只读取这两个位置 - 从库的
init卷必须挂载 SQL 脚本到/docker-entrypoint-initdb.d/,否则init-replica.sql不会自动执行 - 主库不需要挂载初始化 SQL,但必须提前创建复制用户;否则从库连不上,
START SLAVE直接报ERROR 1045 (28000): Access denied
my.cnf 里 server-id 和 binlog_format 写错就全崩
MySQL 5.7 主从最常卡在 SHOW SLAVE STATUS\G 显示 Slave_IO_Running: No 或 Seconds_Behind_Master: NULL,90% 是这两项配置出问题:
-
server-id必须全局唯一且为整数:主库写1,从库分别写2、3;写成server-id = "1"(带引号)或server-id = 0都会导致 MySQL 启动失败或复制拒绝 -
binlog_format必须设为ROW:MySQL 5.7 默认是MIXED,但某些非确定性语句(如INSERT ... SELECT RAND())在从库重放时可能出错;生产环境务必显式写binlog_format=row - 主库必须开
log-bin,路径别写绝对路径(如/var/lib/mysql/mysql-bin),只写文件名(如mysql-bin),否则启动报错Can't generate a random number - 从库加
read-only=1是安全底线,但不能漏掉super_read_only=1,否则管理员仍可写入,破坏主从一致性
init-replica.sql 的 MASTER_LOG_FILE 和 MASTER_LOG_POS 怎么填?
这个 SQL 脚本不能直接写死 mysql-bin.000001 和 154 —— 这是主库第一次启动后的初始偏移,但 Docker 容器重启、镜像重建后 binlog 文件名和 pos 都会变。
正确做法分两步:
- 先
docker-compose up -d mysql-master启动主库,等它完全就绪(docker logs mysql-master | grep "MySQL init process done.") - 进主库执行:
mysql -uroot -p123456 -e "SHOW MASTER STATUS;",拿到当前File和Position值 - 把这两个值替换进
init/init-replica.sql,再docker-compose up -d mysql-slave1 mysql-slave2 - 注意:如果从库已启动过,
CHANGE MASTER TO前必须先STOP SLAVE;,否则报错ERROR 1201 (HY000)
Docker Compose 启动后还要手动验证复制状态
即使所有容器都 Up 了,也不代表主从通了。必须逐个检查:
- 主库上执行
SHOW PROCESSLIST;,确认有Binlog Dump线程在运行(说明从库已连上) - 从库上执行
SHOW SLAVE STATUS\G,重点看这三项:Slave_IO_Running: Yes、Slave_SQL_Running: Yes、Seconds_Behind_Master: 0 - 如果
Seconds_Behind_Master是NULL,说明 IO 线程没连上主库(常见于密码错、防火墙、server-id冲突);如果是正数,说明 SQL 线程在追,但还没追平 - 测试写入:主库建库建表插入一行,几秒后从库查同表,不能只看表结构是否存在,要查数据是否一致
最易被忽略的是 super_read_only=1 没生效,或者从库 relay-log 路径权限不对导致 SQL 线程 crash,这些都不会让容器退出,但复制实际卡死。











