一、引言
在数据库管理中,MySQL 主从复制是一种非常重要的技术,它可以实现数据的备份、读写分离,减轻主数据库的压力。本文将详细介绍如何使用 Docker 和 Harbor 仓库来搭建 MySQL 主从复制环境,适合刚接触数据库和 Docker 的新手学习。
二、MySQL 主从复制原理
2.1 基本概念
主从复制是指一台服务器充当主数据库服务器(Master),另一台或多台服务器充当从数据库服务器(Slave),主服务器中的数据会自动复制到从服务器之中。对于多级复制,数据库服务器既可以充当主机,也可以充当从机。MySQL 主从复制的基础是主服务器对数据库修改记录二进制日志,从服务器通过主服务器的二进制日志自动执行更新。
2.2 角色职责
- 主数据库(Master):负责处理写操作和更新数据,是业务操作的主要入口。
- 从数据库(Slave):复制主数据库的数据,通常用于读操作和数据备份,以减轻主数据库的压力。
2.3 复制流程
- 主库记录并发送日志:
- 当主库发生更新事件(如
UPDATE、INSERT、DELETE、CREATE)时,这些操作会被顺序地写入二进制日志(binlog)中。 - 主库会开启一个
binlog dump线程,负责将binlog日志中的事件发送给从库。
- 当主库发生更新事件(如
- 从库接收并写入中继日志:
- 从库通过
IO线程连接到主库,并请求binlog日志的内容。 - 主库的
binlog dump线程将binlog日志中的事件发送给从库的IO线程。 - 从库的
IO线程接收这些事件,并将其写入到从库的中继日志(relay log)中。
- 从库通过
- 从库同步数据:
- 从库开启一个
SQL线程,实时监控relay log的内容是否有更新。 SQL线程解析relay log中的SQL语句,并在从库上执行这些语句,从而实现数据的同步。
- 从库开启一个

三、拉取 MySQL 镜像
3.1 从 Harbor 仓库拉取镜像
可以使用以下命令从 Harbor 仓库拉取 MySQL 9.3.0 版本的镜像:
[root@mysql docker]# docker pull harbor.registry.com/library/mysql:9.3.0
参数解释:
docker pull:用于从镜像仓库中拉取镜像。harbor.registry.com/library/mysql:9.3.0:指定要拉取的镜像的地址和版本,harbor.registry.com是 Harbor 仓库的地址,library/mysql是镜像的名称,9.3.0是镜像的版本号。
如果没有仓库,可以直接执行这个命令:
docker pull mysql:9.3.0
尝试从 Docker Hub(官方 Docker 镜像仓库)拉取 mysql 镜像的 9.3.0 版本。Docker Hub 是 Docker 官方的公共镜像仓库,当你使用 docker pull 命令并且不指定具体仓库地址时,Docker 客户端默认会从 Docker Hub 拉取镜像。
3.2 检查镜像是否拉取成功
使用以下命令查看本地镜像列表:
[root@mysql docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
harbor.registry.com/library/mysql 9.3.0 2c849dee4ca9 5 weeks ago 859MB
参数解释:
docker images:用于列出本地所有的镜像,显示镜像的仓库名、标签、镜像 ID、创建时间和大小等信息。
3.3 处理拉取镜像时的 TLS 证书验证失败问题
如果在使用 docker pull 命令拉取镜像时,由于 TLS 证书验证失败导致报错,例如:
[root@mysql docker]# docker pull harbor.registry.com/library/mysql:9.3.0
Error response from daemon: Get "https://harbor.registry.com/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
可以创建 /etc/docker/daemon.json 文件,并写入以下内容:
{
"default-ipc-mode": "shareable",
"data-root": "/data/docker",
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "50"
},
"insecure-registries": ["https://harbor.registry.com"],
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.imgdb.de",
"https://docker-0.unsee.tech",
"https://docker.hlmirror.com",
"https://docker.1ms.run",
"https://func.ink",
"https://lispy.org",
"https://docker.xiaogenban1993.com"
]
}
参数解释:
default-ipc-mode:设置默认的 IPC(进程间通信)模式为shareable。data-root:指定 Docker 数据存储的根目录为/data/docker。exec-opts:设置容器执行时的选项,native.cgroupdriver=systemd表示使用systemd作为 cgroup 驱动。log-driver:指定日志驱动为json-file,将容器日志以 JSON 文件的形式存储。log-opts:设置日志的选项,max-size表示单个日志文件的最大大小为100m,max-file表示最多保留50个日志文件。insecure-registries:添加不安全的镜像仓库地址,允许从该仓库拉取镜像,这里是https://harbor.registry.com。registry-mirrors:设置镜像加速地址,提高镜像拉取的速度。
3.4 添加 Harbor 仓库映射
在 /etc/hosts 文件中添加 Harbor 仓库的映射:
[root@mysql docker]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.220.20 harbor.registry.com harbor
参数解释:
/etc/hosts:是一个本地的域名解析文件,通过添加192.168.220.20 harbor.registry.com harbor这一行,将harbor.registry.com域名映射到192.168.220.20这个 IP 地址。
注意:
四、启动 MySQL 容器
4.1 启动初始容器
使用以下命令启动一个 MySQL 容器:
[root@mysql docker]# docker run --name mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD="123456" harbor.registry.com/library/mysql:9.3.0
参数解释:
docker run:用于创建并启动一个新的容器。--name mysql:为容器指定一个名称为mysql。-d:表示在后台运行容器。-p 3306:3306:将宿主机的3306端口映射到容器内部的3306端口,这样可以通过宿主机的3306端口访问容器内的 MySQL 服务。-e MYSQL_ROOT_PASSWORD="123456":设置容器内 MySQL 的 root 用户密码为123456。harbor.registry.com/library/mysql:9.3.0:指定要使用的镜像。
4.2 检查容器是否启动成功
使用以下命令查看正在运行的容器:
[root@mysql docker]# docker ps
参数解释:
docker ps:用于列出正在运行的容器,显示容器的 ID、镜像、命令、创建时间、状态、端口映射和名称等信息。
4.3 查看容器日志
如果容器启动报错,可以使用以下命令查看容器的日志,以寻找出错原因:
[root@mysql docker]# docker logs mysql
参数解释:
docker logs:用于查看指定容器的日志信息,mysql是容器的名称。
4.4 进入容器
使用以下命令进入正在运行的容器:
[root@mysql docker]# docker exec -it mysql /bin/bash
参数解释:
docker exec:用于在运行的容器中执行命令。-it:表示以交互模式进入容器,-i保持标准输入打开,-t分配一个伪终端。mysql:是容器的名称。/bin/bash:指定要执行的命令,即进入容器的bash终端。
bash-5.1# cd etc
bash-5.1# ls
# 找到my.cnf文件
五、配置主从服务器
5.1 复制配置文件
在新的会话窗口中创建两个目录:
[root@mysql docker]# mkdir /data/master/conf -p
[root@mysql docker]# mkdir /data/slave/conf -p
参数解释:
mkdir:用于创建目录。-p:表示如果父目录不存在,则先创建父目录。
将刚刚找到的 my.cnf 配置文件,并将其拷贝到 /data/master/conf 目录下:
[root@mysql docker]# cd /data/master/conf/
[root@mysql conf]# docker cp mysql:/etc/my.cnf .
参数解释:
cd etc:进入容器的etc目录。ls:列出当前目录下的文件和文件夹。exit:退出容器。docker cp:用于在宿主机和容器之间复制文件,mysql:/etc/my.cnf表示容器mysql内的/etc/my.cnf文件,.表示当前目录。
5.2 修改配置文件
编辑 /data/master/conf/my.cnf 文件,添加 server-id=1:
[root@mysql conf]# vim /data/master/conf/my.cnf
参数解释:
vim:是一个文本编辑器,用于编辑文件内容。server-id=1:为 MySQL 服务器指定一个唯一的 ID,主服务器的 ID 通常为1。
将修改后的 my.cnf 文件拷贝到 /data/slave/conf 文件夹下面,并将 server-id 的值改为 2:
[root@mysql conf]# cp my.cnf ../../slave/conf/
[root@mysql conf]# vim /data/slave/conf/my.cnf
参数解释:
cp:用于复制文件,my.cnf是要复制的文件,../../slave/conf/是目标目录。server-id=2:从服务器的 ID 需要与主服务器不同,这里设置为2。

5.3 停止并删除初始容器
退出容器后,停掉并删除初始容器:
bash-5.1# exit
[root@mysql docker]# docker stop mysql
[root@mysql docker]# docker rm mysql
参数解释:
docker stop:用于停止正在运行的容器,mysql是容器的名称。docker rm:用于删除容器,mysql是容器的名称。
查看发现,容器已经删除,没有任何容器了:
[root@mysql docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
六、创建主服务器
使用以下命令创建主服务器容器:
[root@mysql docker]# docker run -d \
--name mysql-master \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /data/master/conf/my.cnf:/etc/my.cnf \
-p 3306:3306 \
harbor.registry.com/library/mysql:9.3.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
参数解释:
-d:在后台运行容器。--name mysql-master:为容器指定名称为mysql-master。-e MYSQL_ROOT_PASSWORD=123456:设置容器内 MySQL 的 root 用户密码为123456。-v /data/master/conf/my.cnf:/etc/my.cnf:将宿主机的/data/master/conf/my.cnf文件挂载到容器内的/etc/my.cnf文件,实现配置文件的持久化。-p 3306:3306:将宿主机的3306端口映射到容器内部的3306端口。harbor.registry.com/library/mysql:9.3.0:指定要使用的镜像。--character-set-server=utf8mb4:设置服务器的字符集为utf8mb4。--collation-server=utf8mb4_unicode_ci:设置服务器的排序规则为utf8mb4_unicode_ci。
6.1 进入主服务器容器
使用以下命令进入主服务器容器:
[root@mysql docker]# docker exec -it mysql-master /bin/bash
bash-5.1# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 9.3.0 MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
参数解释:
docker exec -it mysql-master /bin/bash:以交互模式进入mysql-master容器的bash终端。mysql -uroot -p123456:使用 root 用户和密码123456登录 MySQL。
6.2 创建用户并授权
在主服务器的 MySQL 中创建一个用于同步的用户,并授予其复制从服务器的权限:
# 创建用户:
mysql> create user 'backups'@'%' identified by '123456';
Query OK, 0 rows affected (0.021 sec)
# 给权限:
mysql> grant replication slave on *.* to 'backups'@'%';
Query OK, 0 rows affected (0.003 sec)
# 刷新权限:
mysql> flush privileges;
Query OK, 0 rows affected, 1 warning (0.003 sec)
参数解释:
create user 'backups'@'%' identified by '123456':创建一个名为backups的用户,允许从任何主机连接,密码为123456。grant replication slave on *.* to 'backups'@'%':授予backups用户在所有数据库和所有表上的复制从服务器的权限。flush privileges:刷新权限,使新的权限设置生效。
6.3 查看同步起始位置
使用以下命令查看主服务器的二进制日志状态,获取同步的起始位置:
mysql> show binary log status;
-- 或者
mysql> show binary log status\G;
例如:
mysql> show binary log status;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000002 | 863 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.000 sec)
mysql> show binary log status\G;
*************************** 1. row ***************************
File: binlog.000002
Position: 863
Binlog_Do_DB:
Binlog_Ignore_DB:
Executed_Gtid_Set:
1 row in set (0.001 sec)
ERROR:
No query specified
参数解释:
show binary log status:显示主服务器的二进制日志状态,包括当前正在使用的二进制日志文件、位置等信息。\G:以垂直格式显示查询结果,方便查看。
七、创建从服务器
7.1 创建从服务器容器
在新的窗口中使用以下命令创建从服务器容器:
[root@mysql conf]# docker run -d \
--name mysql-slave \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /data/slave/conf/my.cnf:/etc/my.cnf \
-p 3307:3306 \
harbor.registry.com/library/mysql:9.3.0 \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci
参数解释:
- 大部分参数与创建主服务器容器的参数相同,不同之处在于:
--name mysql-slave:为容器指定名称为mysql-slave。-p 3307:3306:将宿主机的3307端口映射到容器内部的3306端口,避免与主服务器的端口冲突。
7.2 进入从服务器容器
使用以下命令进入从服务器容器:
[root@mysql conf]# docker exec -it mysql-slave /bin/bash
bash-5.1# mysql -uroot -p123456
参数解释:
- 与进入主服务器容器的命令和参数解释相同。
7.3 配置主从复制
在从服务器的 MySQL 中配置主从复制:
mysql> CHANGE REPLICATION SOURCE TO \
SOURCE_HOST='192.168.220.198',SOURCE_USER='backups',SOURCE_PASSWORD='123456', \
SOURCE_LOG_FILE='binlog.000002',SOURCE_LOG_POS=863,GET_SOURCE_PUBLIC_KEY=1;
参数解释:
CHANGE REPLICATION SOURCE TO:用于配置从服务器的复制源。SOURCE_HOST='192.168.220.198':指定主服务器的 IP 地址。SOURCE_USER='backups':指定用于复制的用户。SOURCE_PASSWORD='123456':指定用于复制的用户的密码。SOURCE_LOG_FILE='binlog.000002':指定主服务器的二进制日志文件。SOURCE_LOG_POS=863:指定主服务器二进制日志的起始位置。GET_SOURCE_PUBLIC_KEY=1:表示获取主服务器的公钥。
7.4 启动复制并查看状态
执行以下命令启动复制,并查看复制状态:
mysql> start replica;
mysql> show replica status\G;
参数解释:
start replica:启动从服务器的复制进程。show replica status\G:显示从服务器的复制状态,以垂直格式显示结果,方便查看各个参数的值。
八、验证主从复制
8.1 在主服务器创建测试数据库和表
进入主服务器容器并登录 MySQL:
[root@mysql docker]# docker exec -it mysql-master /bin/bash
bash-5.1# mysql -uroot -p123456
在 MySQL 中创建一个测试数据库和表,并插入一些数据:
mysql> CREATE DATABASE test_db;
Query OK, 1 row affected (0.00 sec)
mysql> USE test_db;
Database changed
mysql> CREATE TABLE test_table (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO test_table (name) VALUES ('test_value');
Query OK, 1 row affected (0.00 sec)
8.2 在从服务器验证数据同步
进入从服务器容器并登录 MySQL:
[root@mysql docker]# docker exec -it mysql-slave /bin/bash
bash-5.1# mysql -uroot -p123456
在 MySQL 中检查是否能看到主服务器创建的数据库和表,以及插入的数据:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test_db |
+--------------------+
mysql> USE test_db;
Database changed
mysql> SELECT * FROM test_table;
+----+------------+
| id | name |
+----+------------+
| 1 | test_value |
+----+------------+
如果能在从服务器看到主服务器创建的数据库、表和插入的数据,说明主从复制配置成功。
九、总结
通过以上步骤,我们成功地使用 Docker 和 Harbor 仓库搭建了 MySQL 主从复制环境,并完成了验证。主从复制可以提高数据库的可用性、读写性能和数据安全性,在实际的生产环境中有着广泛的应用。希望本文对刚接触 MySQL 和 Docker 的新手有所帮助。
以上就是完整的 MySQL 主从复制搭建及验证过程,每一步都有详细的命令参数解释,相信新手也能轻松理解和操作。







![[LevelDB]LevelDB版本管理的黑魔法-为什么能在不锁表的情况下管理数据?](https://i-blog.csdnimg.cn/direct/14f261691c814b5abd256b79d9b70299.png)












