Docker 搭建 MySQL 主从服务实战操作详解

Docker 搭建 MySQL 主从服务实战操作详解

适用版本:MySQL 8.0+、Docker 20.10+


前言

在高可用、读写分离、数据备份等场景中,MySQL 主从复制(Master-Slave Replication)是基础且关键的技术。本文将通过 Docker 容器化方式,手把手教你搭建一套完整的 MySQL 主从复制环境,涵盖网络配置、权限设置、GTID 启用、复制启动与验证等细节,确保每一步都清晰可复现。


一、准备工作

1.1 环境要求

  • 操作系统:Linux / macOS / Windows(WSL2 推荐)
  • Docker 已安装并正常运行
  • 至少 2GB 可用内存(主从各需约 512MB~1GB)
  • 端口未被占用(主库 3307,从库 3308)

⚠️ 注意:为避免与本地 MySQL 冲突,本文使用非默认端口。

1.2 规划架构

角色 容器名 IP 地址(自定义网络) 端口映射 数据目录
主库 mysql-master 172.20.0.10 3307 ./master/data
从库 mysql-slave 172.20.0.11 3308 ./slave/data

我们将创建一个自定义 Docker 网络 mysql-net,确保容器间可通过固定 IP 通信。


二、创建自定义网络

bash 复制代码
docker network create --driver bridge --subnet=172.20.0.0/24 mysql-net

验证网络:

bash 复制代码
docker network inspect mysql-net

应看到 "Subnet": "172.20.0.0/24"


三、准备配置文件

3.1 创建项目目录结构

bash 复制代码
mkdir -p mysql-replication/{master,slave}/{conf,data}
cd mysql-replication

最终目录结构如下:

复制代码
mysql-replication/
├── master/
│   ├── conf/
│   │   └── my.cnf
│   └── data/
└── slave/
    ├── conf/
    │   └── my.cnf
    └── data/

3.2 配置主库 my.cnf(master/conf/my.cnf)

ini 复制代码
[mysqld]
# 基础设置
server-id = 1
port = 3306
bind-address = 0.0.0.0
datadir = /var/lib/mysql
socket = /var/run/mysqld/mysqld.sock

# 复制相关
log-bin = mysql-bin
binlog_format = ROW
binlog_expire_logs_seconds = 604800  # 7天过期
gtid_mode = ON
enforce_gtid_consistency = ON

# 其他优化(可选)
max_connections = 200
innodb_buffer_pool_size = 256M

✅ 关键点:

  • server-id 必须唯一(主=1,从≠1)
  • 启用 log-bin 是主库必备
  • GTID 模式简化复制管理,推荐开启

3.3 配置从库 my.cnf(slave/conf/my.cnf)

ini 复制代码
[mysqld]
server-id = 2
port = 3306
bind-address = 0.0.0.0
datadir = /var/lib/mysql
socket = /var/run/mysqld/mysqld.sock

# 从库也需要启用 binlog(便于级联或故障切换)
log-bin = mysql-bin
relay-log = relay-bin
read_only = ON
gtid_mode = ON
enforced_gtid_consistency = ON

# 其他
max_connections = 200
innodb_buffer_pool_size = 256M

⚠️ 注意:read_only = ON 防止从库被误写(但 SUPER 权限用户仍可写)


四、启动 MySQL 主从容器

4.1 启动主库容器

bash 复制代码
docker run -d \
  --name mysql-master \
  --network mysql-net \
  --ip 172.20.0.10 \
  -p 3307:3306 \
  -v $(pwd)/master/conf/my.cnf:/etc/mysql/my.cnf:ro \
  -v $(pwd)/master/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=Root@123456 \
  --restart=unless-stopped \
  mysql:8.0

4.2 启动从库容器

bash 复制代码
docker run -d \
  --name mysql-slave \
  --network mysql-net \
  --ip 172.20.0.11 \
  -p 3308:3306 \
  -v $(pwd)/slave/conf/my.cnf:/etc/mysql/my.cnf:ro \
  -v $(pwd)/slave/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=Root@123456 \
  --restart=unless-stopped \
  mysql:8.0

🔍 参数说明:

  • -v ...:ro:配置文件只读挂载
  • --ip:指定固定 IP,便于从库连接主库
  • --restart=unless-stopped:容器自动重启

4.3 等待容器初始化完成

bash 复制代码
# 查看日志,确认无报错
docker logs -f mysql-master
docker logs -f mysql-slave

等待出现 mysqld: ready for connections 即可继续。


五、配置主库复制账户

5.1 进入主库容器

bash 复制代码
docker exec -it mysql-master mysql -uroot -p
# 输入密码:Root@123456

5.2 创建用于复制的专用用户

sql 复制代码
CREATE USER 'repl'@'%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;

✅ 安全建议:

  • 不要使用 root 用户做复制
  • 密码强度足够
  • 可限制 IP(如 'repl'@'172.20.0.11'

5.3 查看主库状态(记录 GTID 或 binlog 位置)

sql 复制代码
SHOW MASTER STATUS\G

输出示例:

复制代码
*************************** 1. row ***************************
             File: mysql-bin.000002
         Position: 156
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee:1-5

📌 在 GTID 模式下,我们主要关注 Executed_Gtid_Set,传统模式才需 File + Position


六、配置从库连接主库

6.1 进入从库容器

bash 复制代码
docker exec -it mysql-slave mysql -uroot -p
# 密码:Root@123456

6.2 设置主从关系(GTID 模式)

sql 复制代码
CHANGE MASTER TO
  MASTER_HOST='172.20.0.10',
  MASTER_PORT=3306,
  MASTER_USER='repl',
  MASTER_PASSWORD='Repl@123456',
  MASTER_AUTO_POSITION=1;  -- 关键!启用 GTID 自动定位

MASTER_AUTO_POSITION=1 表示使用 GTID 自动同步,无需手动指定 binlog 文件和位置。

6.3 启动从库复制线程

sql 复制代码
START SLAVE;

6.4 检查复制状态

sql 复制代码
SHOW SLAVE STATUS\G

重点关注以下字段:

字段 正常值
Slave_IO_Running Yes
Slave_SQL_Running Yes
Seconds_Behind_Master 0(或很小)
Last_IO_Error / Last_SQL_Error (空)

❌ 若出现错误,需根据具体信息排查(常见:网络不通、账号密码错误、GTID 不一致等)


七、验证主从复制

7.1 在主库创建测试数据库和表

sql 复制代码
-- 主库执行
CREATE DATABASE test_replication;
USE test_replication;
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');

7.2 在从库查询数据

sql 复制代码
-- 从库执行
SHOW DATABASES;
USE test_replication;
SELECT * FROM users;

应看到与主库完全一致的数据。

✅ 成功!主从复制已生效。


八、常见问题排查

8.1 从库无法连接主库

  • 检查 docker network inspect mysql-net 确认 IP 正确
  • 在从库容器内 ping 172.20.0.10 测试连通性
  • 检查主库是否监听 0.0.0.0(非 127.0.0.1

8.2 复制线程未启动

  • 执行 STOP SLAVE; START SLAVE; 重启
  • 查看 SHOW SLAVE STATUS 中的错误信息

8.3 GTID 不一致导致复制中断

  • 若从库有独立写入(不推荐),可能导致 GTID 冲突
  • 解决方案:重做从库(清空数据目录,重新配置)

九、停止与清理

bash 复制代码
# 停止并删除容器
docker stop mysql-master mysql-slave
docker rm mysql-master mysql-slave

# 删除数据(谨慎!)
rm -rf master/data slave/data

# 删除网络
docker network rm mysql-net

十、总结

通过本文,你已掌握:

✅ 使用 Docker 快速部署 MySQL 主从

✅ 配置 GTID 模式实现自动位点同步

✅ 创建专用复制账号提升安全性

✅ 验证复制效果并排查常见问题

💡 进阶建议

  • 结合 docker-compose.yml 管理多容器
  • 添加监控(如 Prometheus + mysqld_exporter)
  • 配置半同步复制提升数据一致性

附录:docker-compose.yml 示例(可选)

yaml 复制代码
version: '3.8'
services:
  mysql-master:
    image: mysql:8.0
    container_name: mysql-master
    networks:
      mysql-net:
        ipv4_address: 172.20.0.10
    ports:
      - "3307:3306"
    volumes:
      - ./master/conf/my.cnf:/etc/mysql/my.cnf:ro
      - ./master/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: Root@123456
    restart: unless-stopped

  mysql-slave:
    image: mysql:8.0
    container_name: mysql-slave
    networks:
      mysql-net:
        ipv4_address: 172.20.0.11
    ports:
      - "3308:3306"
    volumes:
      - ./slave/conf/my.cnf:/etc/mysql/my.cnf:ro
      - ./slave/data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: Root@123456
    restart: unless-stopped

networks:
  mysql-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

使用命令:

bash 复制代码
docker-compose up -d

🎉 恭喜你,成功搭建了高可用的 MySQL 主从架构!如有疑问,欢迎交流。

相关推荐
qq_348231858 小时前
MySQL 与 PostgreSQL PL/pgSQL 的对比详解
数据库·mysql·postgresql
cui_win8 小时前
Prometheus实战教程 - mysql监控
mysql·prometheus·压测
wsx_iot8 小时前
mysql的快照读和当前读
数据库·mysql
梁萌8 小时前
MySQL分区表使用保姆级教程
数据库·mysql·优化·分区表·分区·partitions
Logic1019 小时前
《数据库运维》 郭文明 实验4 数据库备份与恢复实验核心操作与思路解析
运维·数据库·sql·mysql·学习笔记·形考作业·国家开放大学
嗑瓜子儿溜茶水儿9 小时前
docker 部署 kkfileview ; arm64; ky10;
java·docker
hssfscv10 小时前
Mysql学习笔记——多表查询
笔记·学习·mysql
MC皮蛋侠客10 小时前
MySQL数据库迁移脚本及使用说明
数据库·mysql
九思x10 小时前
通过docker-compose.yml文件一次性安装mysql、minio、redis服务
运维·docker·容器