Docker Compose 构建 MySQL 数据库主从复制实例
由于是在单机上同时运行主从实例,因此仅用于开发环境或学习主从复制配置。
项目地址 github.com/TomCzHen/my...
文件结构
├── docker-compose.yaml
├── env
│ ├── base.env
│ ├── master.env
│ └── node.env
├── .env
├── init-db-sql
│ ├── init-master.sh
│ ├── init-node.sh
│ ├── sakila-data.sql
│ └── sakila-schema.sql
└── README.md
复制代码
env
.env .yaml
而env下的文件
路径有除了容器内部环境变量之外的其他功能。
.env
TAG=5.7.20
MASTER_SERVER_ID=1
NODE_1_SERVER_ID=10
NODE_2_SERVER_ID=20
MASTER_MYSQL_ROOT_PASSWORD=master_root_pwd
NODE_MYSQL_ROOT_PASSWORD=node_root_pwd
复制代码
docker-compose.yaml
version: "3.3"
services:
mysql-master: &mysql
image: mysql:${TAG}
container_name: mysql-master
restart: unless-stopped
env_file:
- env/base.env
- env/master.env
environment:
- MYSQL_ROOT_PASSWORD=${MASTER_MYSQL_ROOT_PASSWORD}
ports:
- "3306:3306"
expose:
- "3306"
volumes:
- mysql-master-data:/var/lib/mysql
- ./init-db-sql/sakila-schema.sql:/docker-entrypoint-initdb.d/1-schema.sql
- ./init-db-sql/sakila-data.sql:/docker-entrypoint-initdb.d/2-data.sql
- ./init-db-sql/init-master.sh:/docker-entrypoint-initdb.d/3-init-master.sh
command: [
"--log-bin=mysql-bin",
"--server-id=${MASTER_SERVER_ID}",
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_unicode_ci",
"--innodb_flush_log_at_trx_commit=1",
"--sync_binlog=1"
]
mysql-node-1: &mysql-node
<<: *mysql
container_name: mysql-node-1
env_file:
- env/base.env
- env/node.env
environment:
- MYSQL_ROOT_PASSWORD=${NODE_MYSQL_ROOT_PASSWORD}
- MASTER_MYSQL_ROOT_PASSWORD=${MASTER_MYSQL_ROOT_PASSWORD}
ports:
- "3307:3306"
depends_on:
- mysql-master
volumes:
- mysql-node-1-data:/var/lib/mysql
- ./init-db-sql/sakila-schema.sql:/docker-entrypoint-initdb.d/1-schema.sql
- ./init-db-sql/sakila-data.sql:/docker-entrypoint-initdb.d/2-data.sql
- ./init-db-sql/init-node.sh:/docker-entrypoint-initdb.d/3-init-node.sh
command: [
"--server-id=${NODE_1_SERVER_ID}",
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_unicode_ci",
]
mysql-node-2:
<<: *mysql-node
container_name: mysql-node-2
ports:
- "3308:3306"
volumes:
- mysql-node-2-data:/var/lib/mysql
- ./init-db-sql/sakila-schema.sql:/docker-entrypoint-initdb.d/1-schema.sql
- ./init-db-sql/sakila-data.sql:/docker-entrypoint-initdb.d/2-data.sql
- ./init-db-sql/init-node.sh:/docker-entrypoint-initdb.d/3-init-node.sh
command: [
"--server-id=${NODE_2_SERVER_ID}",
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_unicode_ci",
]
volumes:
mysql-master-data:
mysql-node-1-data:
mysql-node-2-data:
复制代码
由于使用YAML引用语法,所以可以通过docker-compose config
看到全部内容。这里配置了一个主数据库和两个从数据库。从数据库的数量可以根据需要更改。
初始化实例
...
volumes:
- mysql-master-data:/var/lib/mysql
- ./init-db-sql/sakila-schema.sql:/docker-entrypoint-initdb.d/1-schema.sql
- ./init-db-sql/sakila-data.sql:/docker-entrypoint-initdb.d/2-data.sql
- ./init-db-sql/init-master.sh:/docker-entrypoint-initdb.d/3-init-master.sh
...
复制代码
初始化时将按照文件名顺序执行基础镜像(仅第一次运行) /docker-entrypoint-initdb.d
❝❀❙ .sh等文件。详细信息请参见镜像描述页面:
hub.docker.com/_/mysql/
初始化新实例
容器第一次启动时,会生成指定名称的新数据库将使用提供的配置变量创建和初始化。此外,它将运行文件扩展名为 .sh
、.sql
和 .sql 的文件。 gz
位于/docker-entrypoint-initdb.d
。这些文件将按字母顺序执行。您可以通过在该目录中安装 SQL 转储并提供带有贡献数据的自定义映像来轻松填充 mysql 服务。 SQL文件默认导入到变量MYSQL_DATABASE
.
指定的数据库注意:sakila
是MySdocl dev.com.mySdocl/sakila.com的官方示例数据库。 /…
配置实例参数
...
command: [
"--log-bin=mysql-bin",
"--server-id=${MASTER_SERVER_ID}",
"--character-set-server=utf8mb4",
"--collation-server=utf8mb4_unicode_ci",
"--innodb_flush_log_at_trx_commit=1",
"--sync_binlog=1"
]
...
复制代码
使用执行参数,可以不依赖my.cnf
配置实例。详细信息请参见镜像描述页面:
hub.docker.com ///mysql/
无 cnf 的配置文件 许多配置选项可以作为标志传递给mysqld
。这使您可以灵活地自定义容器,而无需使用 cnf
文件。例如,如果您想要更改所有表的默认编码和排序规则以使用 UTF-8 (utf8mb4),只需运行以下命令:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
复制代码
如果您想查看可用选项的完整列表,只需运行:
$ docker run -it --rm mysql:tag --verbose --help
复制代码
主从配置
init-master .sh
#!/bin/bash
set -e
# create replication user
mysql_net=$(ip route | awk '$1=="default" {print $3}' | sed "s/\.[0-9]\+$/.%/g")
MYSQL_PWD=${MYSQL_ROOT_PASSWORD} mysql -u root \
-e "CREATE USER '${MYSQL_REPLICATION_USER}'@'${mysql_net}' IDENTIFIED BY '${MYSQL_REPLICATION_PASSWORD}'; \
GRANT REPLICATION SLAVE ON *.* TO '${MYSQL_REPLICATION_USER}'@'${mysql_net}';"
复制代码
在主目录中添加用于复制的帐户。由于默认启用镜像,参数为--skip-name-resolve
,因此只能通过IP
配置权限 注:脚本中是获取容器默认网关后添加用户网段不适合生产环境。
init-node.sh
#!/bin/bash
# check mysql master run status
set -e
until MYSQL_PWD=${MASTER_MYSQL_ROOT_PASSWORD} mysql -u root -h mysql-master ; do
>&2 echo "MySQL master is unavailable - sleeping"
sleep 3
done
# create replication user
mysql_net=$(ip route | awk '$1=="default" {print $3}' | sed "s/\.[0-9]\+$/.%/g")
MYSQL_PWD=${MYSQL_ROOT_PASSWORD} mysql -u root \
-e "CREATE USER '${MYSQL_REPLICATION_USER}'@'${mysql_net}' IDENTIFIED BY '${MYSQL_REPLICATION_PASSWORD}'; \
GRANT REPLICATION SLAVE ON *.* TO '${MYSQL_REPLICATION_USER}'@'${mysql_net}';"
# get master log File & Position
master_status_info=$(MYSQL_PWD=${MASTER_MYSQL_ROOT_PASSWORD} mysql -u root -h mysql-master -e "show master status\G")
LOG_FILE=$(echo "${master_status_info}" | awk 'NR!=1 && $1=="File:" {print $2}')
LOG_POS=$(echo "${master_status_info}" | awk 'NR!=1 && $1=="Position:" {print $2}')
# set node master
MYSQL_PWD=${MYSQL_ROOT_PASSWORD} mysql -u root \
-e "CHANGE MASTER TO MASTER_HOST='mysql-master', \
MASTER_USER='${MYSQL_REPLICATION_USER}', \
MASTER_PASSWORD='${MYSQL_REPLICATION_PASSWORD}', \
MASTER_LOG_FILE='${LOG_FILE}', \
MASTER_LOG_POS=${LOG_POS};"
# start slave and show slave status
MYSQL_PWD=${MYSQL_ROOT_PASSWORD} mysql -u root -e "START SLAVE;show slave status\G"
复制代码
从库配置时,会先等待主库准备好,然后从从库中取出连接主库所需的参数值,初始化从库,并开启从库的复制模式。
使用指南
根据需要调整变量值和脚本,修改docker-compose.yaml
中每个实例暴露的端口并在部署编排中执行-dockerd-op项目库。
使用docker-compose logs mysql-master
查看对应容器输出日志。
使用docker exec -ti mysql-master bash
进入对应的容器控制台环境。
第二
GTID 模式需要调整脚本和编排文件中的执行参数。如果想使用容器将从库添加到现有实例中,修改 init-node.sh
将 File 和 Position 作为环境变量传递会更合适。
作者:TomCzHen
链接:https://juejin.im/post/5a2e4bd66fb9a044fa19cfb7
来源:掘金版权归作者所有。商业转载请联系作者获取授权。非商业转载请注明出处。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。