本文是《Docker下MySQL主从三部曲》系列的第二篇,上一篇《Docker下MySQL主从三部曲之一:极速体验》我们轻而易举的搭建了MySQL主从同步环境,凭借的是一个docker-compose.yml脚本,今天我们一起来看看这个脚本相关的技术细节,学习如何制作支持MySQL主从同步镜像;
原文链接:https://blog.csdn.net/boling_cavalry/article/details/79775617
在开始制作镜像前,我们先列出镜像要解决的问题: 主库镜像:
从库镜像:
综上所述,一共有两个问题需要我们重点解决:
第一个问题,可以修改mysql的配置文件my.cnf,增加一个存放配置文件目录,镜像的使用者将自己的配置文件放在这个目录,MySQL启动的时候就能取到里面的配置文件了; 第二个问题,MySQL官方镜像中有个docker-entrypoint.sh文件,这里面加入的SQL可以在容器启动后自动执行,我们就把SQL写在这里面;
先将步骤梳理出来,这样后面思路更清晰,主库和从库的镜像制作步骤是一样的,不同之处在替换官方的my.cnf、docker-entrypoint.sh文件内容不同:
您可以在GitHub下载本章涉及的脚本和配置文件,地址和链接信息如下表所示:
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
这个git项目中有多个目录,本次所需的资源放在 mysql-master-slave目录下,如下图红框所示: ![这里写图片描述](https://img-blog.csdn.net/20180401143106919?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JvbGluZ19jYXZhbHJ5/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
打开mysql-master-slave文件夹里面有两个文件夹,docker-compose中是上一章用到的docker-compose.yml文件以及各容器的配置文件,docker-build中有两个文件夹,分别存放了制作主库和从库所需的全部材料;
主库镜像的Dockerfile内容:
# Docker file from bolingcavalry # VERSION 0.0.1
# Author: bolingcavalry
#基础镜像
FROM mysql:5.7.21
#作者
MAINTAINER BolingCavalry <zq2599@gmail.com>
#定义配置文件存放目录
ENV BASE_CONF_PATH /etc/mysql
#定义存放外部配置文件的文件夹名称
ENV EXTEND_CONF_FILE_FOLDER_NAME extend.conf.d
#定义conf文件名
ENV CONF_FILE_NAME my.cnf
#定义entrypoint文件所在路径
ENV ENTRY_FILE_PATH /usr/local/bin
#定义entrypoint文件名
ENV ENTRY_FILE_NAME docker-entrypoint.sh
#定义entrypoint的软链接文件名
ENV ENTRY_FILE_SOFT_LINK_NAME entrypoint.sh
#删除原有的配置文件
RUN rm $BASE_CONF_PATH/$CONF_FILE_NAME
#复制新的配置文件
COPY ./$CONF_FILE_NAME $BASE_CONF_PATH/
#给shell文件赋读权限
RUN chmod a+r $BASE_CONF_PATH/$CONF_FILE_NAME
#创建存放外部配置文件的目录
RUN mkdir $BASE_CONF_PATH/$EXTEND_CONF_FILE_FOLDER_NAME
#删除原有的软链接
RUN rm -rf /$ENTRY_FILE_SOFT_LINK_NAME
#删除原有的文件
RUN rm -rf $ENTRY_FILE_PATH/$ENTRY_FILE_NAME
#将entrypoint文件复制到原有位置
COPY ./$ENTRY_FILE_NAME $ENTRY_FILE_PATH/
#给entrypoint文件赋读权限
RUN chmod a+x $ENTRY_FILE_PATH/$ENTRY_FILE_NAME
#建立软链接
RUN ln -s $ENTRY_FILE_PATH/$ENTRY_FILE_NAME /$ENTRY_FILE_SOFT_LINK_NAME
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 3306
CMD ["mysqld"]
上述脚本内有详细注释,就不多赘述了,以下三点需要注意:
接下来,我们看看用来覆盖官方镜像中的my.cnf和docker-entrypoint.sh的文件的具体内容;
主库和从库的my.cnf是一模一样的,内容如下所示:
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
!includedir /etc/mysql/extend.conf.d/
与MySQL官方镜像中的同名文件相比,只在尾部增加了一行!includedir /etc/mysql/extend.conf.d/,也就是说/etc/mysql/extend.conf.d/这个文件夹下的配置文件也是MySQL的配置文件;
容器启动后脚本docker-entrypoint.sh会被执行,我们将需要自动执行的SQL放进来,添加SQL的位置在下图红框和绿框之间的位置:
对于主库,我们要加入的内容如下:
echo "CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD' ;" | "${mysql[@]}"
echo "GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD' ;" | "${mysql[@]}"
echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}"
上面三行SQL的功能分别是创建用户、授权、刷新,用到了两个环境变量:MYSQL_REPLICATION_USER、MYSQL_REPLICATION_PASSWORD,在docker-compose.yml中传入了这两个变量的值;
对于从库,我们要加入的内容如下:
if [ "$MYSQL_MASTER_SERVICE_HOST" -a "$MYSQL_REPLICATION_USER" -a "$MYSQL_REPLICATION_PASSWORD" ]; then
echo "STOP SLAVE;" | "${mysql[@]}"
if [ "$MASTER_LOG_FILE" -a "$MASTER_LOG_POS" ]; then
echo "CHANGE MASTER TO master_host='$MYSQL_MASTER_SERVICE_HOST', master_user='$MYSQL_REPLICATION_USER', master_password='$MYSQL_REPLICATION_PASSWORD', master_log_file='$MASTER_LOG_FILE', master_log_pos=$MASTER_LOG_POS ;" | "${mysql[@]}"
else
echo "CHANGE MASTER TO master_host='$MYSQL_MASTER_SERVICE_HOST', master_user='$MYSQL_REPLICATION_USER', master_password='$MYSQL_REPLICATION_PASSWORD' ;" | "${mysql[@]}"
fi
echo "START SLAVE;" | "${mysql[@]}"
fi
上面的脚本中,先检查MYSQL_MASTER_SERVICE_HOST、MYSQL_REPLICATION_USER、MYSQL_REPLICATION_PASSWORD这三个变量是否同时存在,如果存在,就执行设置从库同步的SQL,执行前再检查是否存在MASTER_LOG_FILE和MASTER_LOG_POS参数,用于设置bin log文件名和同步的开始位置,如果有这两个参数就在执行SQL的时候带上,否则就是默认同步所有可以同步的写操作; 设置完毕后,再执行START SLAVE;开启同步;
至此,镜像脚本的开发工作就完成了,执行命令docker build -t bolingcavalry/mysql-master:0.0.1 .完成镜像制作;
让我们再看看docker-compose.yml吧,通过这个脚本我们创建了容器,并且给它们做了一些设置;
docker-compose.yml内容如下:
version: '2'
services:
master:
image: bolingcavalry/mysql-master:0.0.1
environment:
MYSQL_ROOT_PASSWORD: 888888
MYSQL_REPLICATION_USER: rep
MYSQL_REPLICATION_PASSWORD: 888888
volumes:
- ./master:/etc/mysql/extend.conf.d
restart: always
slave0:
image: bolingcavalry/mysql-slave:0.0.1
depends_on:
- master
links:
- master:masterhost
environment:
MYSQL_ROOT_PASSWORD: 888888
MYSQL_MASTER_SERVICE_HOST: masterhost
MYSQL_REPLICATION_USER: rep
MYSQL_REPLICATION_PASSWORD: 888888
volumes:
- ./slave0:/etc/mysql/extend.conf.d
restart: always
slave1:
image: bolingcavalry/mysql-slave:0.0.1
depends_on:
- master
links:
- master:masterhost
environment:
MYSQL_ROOT_PASSWORD: 888888
MYSQL_MASTER_SERVICE_HOST: masterhost
MYSQL_REPLICATION_USER: rep
MYSQL_REPLICATION_PASSWORD: 888888
volumes:
- ./slave1:/etc/mysql/extend.conf.d
restart: always
[mysqld]
log-bin=mysql-bin
server-id=1
5. 从库的设置和主库差不多,有个特别之处就是通过link参数引用了master容器,并且MYSQL_MASTER_SERVICE_HOST参数的值就是link的值 masterhost,这样在docker-entrypoint.sh脚本中,使用MYSQL_MASTER_SERVICE_HOST变量的时候,其实就是master容器的IP地址;
至此,搭建MySQL主从同步环境所做的全部工作已经完成,但是有个小问题还没有搞清楚:在《Docker下手工配置MySQL主从》一文中我们记录下主库的bin log文件名和日志位置,然后设置从库时会用到,但是本章却没有用到这个参数,此参数究竟有什么影响呢?除了看官方文档的参数说明,我们还可以通过实战来验证此参数的作用,这些就留给下一个章节吧,作为《Docker下MySQL主从三部曲》的终篇