Docker单机部署MySQL一主两从需四步:主库启用log-bin并设server-id=1,从库分别设2和3;主库创建mysql_native_password认证的复制用户;从库执行CHANGE REPLICATION SOURCE TO动态指定主库File和Position;挂载目录加:Z标签解决SELinux权限问题。

docker 部署 MySQL 一主两从,不需要 Swarm、不需要跨机器、不需要复杂网络配置——在单机(Mac/Ubuntu/CentOS)上用三组 docker run 命令 + 三个独立配置文件就能跑通,关键是配对 server-id、log-bin 和 CHANGE REPLICATION SOURCE TO 的参数。
主库必须开启 binlog 且 server-id 唯一
MySQL 8.0 默认不开启 binlog,光靠 docker run -e MYSQL_ROOT_PASSWORD=... 启动的容器是无法做主从的。必须挂载自定义 my.cnf 并显式启用:
-
server-id必须是整数,主库设为1,两个从库分别设为2和3(不能重复,否则从库报错ERROR 3021 (HY000): This server has a server_id of 1, but the master has a server_id of 1) -
log-bin名称建议带前缀(如mysql-bin),避免和默认binlog冲突;binlog-format=ROW是安全选择,能规避函数类写法导致的主从不一致 -
binlog-do-db=testdb只同步指定库(可选),但注意:它对跨库语句(如INSERT INTO otherdb.t SELECT * FROM testdb.t)无效,真正可靠的是过滤replicate-do-db在从库侧配置
从库启动后必须手动执行 CHANGE REPLICATION SOURCE TO
MySQL 8.0.23+ 已废弃 CHANGE MASTER TO,新命令是 CHANGE REPLICATION SOURCE TO。它依赖主库当前的 binlog 文件名和 position,这两项必须从主库 SHOW MASTER STATUS 实时获取,不能硬编码。
- 先在主库执行:
SHOW MASTER STATUS→ 记下File(如mysql-bin.000003)和Position(如156) - 再进从库容器:
mysql -uroot -p123456,执行:CHANGE REPLICATION SOURCE TO SOURCE_HOST='host.docker.internal', SOURCE_PORT=3307, SOURCE_USER='slave', SOURCE_PASSWORD='123456', SOURCE_LOG_FILE='mysql-bin.000003', SOURCE_LOG_POS=156; -
SOURCE_HOST填host.docker.internal(Docker Desktop for Mac/Windows 自带),Linux 需改用宿主机真实 IP(如192.168.1.100)或自建 bridge 网络并用容器名
复制用户权限和认证插件容易被忽略
主库创建的复制用户,如果没指定认证插件,MySQL 8.0 默认用 caching_sha2_password,而旧版客户端(包括某些 Docker 内置 mysql 客户端)不支持,会导致从库连接时报 ERROR 2069 (HY000): Unable to connect to source MySQL server。
- 务必在主库执行:
CREATE USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; - 再授权:
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%'; FLUSH PRIVILEGES; - 检查是否生效:
SELECT host,user,plugin FROM mysql.user WHERE user='slave';→ 第三列必须是mysql_native_password - 从库配置文件中也要加:
default-authentication-plugin=mysql_native_password,否则容器启动时可能因 root 用户认证失败卡住
数据目录权限和 SELinux 是 Linux 下最常踩的坑
在 CentOS/RHEL 等启用了 SELinux 的系统上,-v /data/mysql/master/data:/var/lib/mysql 挂载后容器常报 Can't start server: Bind on unix socket: Permission denied 或直接退出,不是配置问题,而是挂载目录缺少 z 或 Z 标签。
- 临时解决:
chcon -Rt svirt_sandbox_file_t /data/mysql/master/data - 一劳永逸:挂载时加
:z(共享标签)或:Z(私有标签),例如:-v /data/mysql/master/data:/var/lib/mysql:Z - 另一个隐形问题:
/data/mysql/master/data目录若非空(比如之前运行过其他 MySQL 容器),docker run会跳过初始化,导致root密码不生效、mysql系统库损坏 —— 首次部署务必清空该目录
实际跑通的关键就这四步:配对 server-id + 开 binlog、动态取 position 执行 CHANGE REPLICATION SOURCE TO、统一认证插件、处理好挂载目录权限。其余都是围绕这四点的细节校验。


















