Docker下MySQL主从三部曲之二:细说镜像制作

本文是《Docker下MySQL主从三部曲》系列的第二篇,上一篇《Docker下MySQL主从三部曲之一:极速体验》我们轻而易举的搭建了MySQL主从同步环境,凭借的是一个docker-compose.yml脚本,今天我们一起来看看这个脚本相关的技术细节,学习如何制作支持MySQL主从同步镜像;

原文链接:https://blog.csdn.net/boling_cavalry/article/details/79775617

镜像要解决的问题

在开始制作镜像前,我们先列出镜像要解决的问题:
主库镜像:
1. 开启bin log,ID是多少,这些问题最好做成可以接受外部传入,交给镜像的使用者去设置,因为多个从库的时候是难以在镜像中分配ID的;
2. 要创建同步账户,并授权;
3. 刷新状态;

从库镜像:
1. 从库的ID设置,像主库一样支持外部传入配置文件,由镜像的使用者来设置;
2. 执行设置同步参数的SQL;
3. 执行启动同步的SQL;

综上所述,一共有两个问题需要我们重点解决:
1. 如何让镜像接受外部传入的配置文件;
2. 如何让容器自动执行指定的SQL;

第一个问题,可以修改mysql的配置文件my.cnf,增加一个存放配置文件目录,镜像的使用者将自己的配置文件放在这个目录,MySQL启动的时候就能取到里面的配置文件了;
第二个问题,MySQL官方镜像中有个docker-entrypoint.sh文件,这里面加入的SQL可以在容器启动后自动执行,我们就把SQL写在这里面;

梳理制作过程

先将步骤梳理出来,这样后面思路更清晰,主库和从库的镜像制作步骤是一样的,不同之处在替换官方的my.cnf、docker-entrypoint.sh文件内容不同:
1. 创建Dockerfile,父镜像是MySQL官方版本:mysql:5.7.21;
2. 用修改过的my.cnf文件替换原有的同名文件;
3. 用修改过的docker-entrypoint.sh文件替换原有的同名文件;

所有脚本的源码

您可以在GitHub下载本章涉及的脚本和配置文件,地址和链接信息如下表所示:

名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) [email protected]:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议


这个git项目中有多个目录,本次所需的资源放在mysql-master-slave目录下,如下图红框所示:
这里写图片描述

打开mysql-master-slave文件夹里面有两个文件夹,docker-compose中是上一章用到的docker-compose.yml文件以及各容器的配置文件,docker-build中有两个文件夹,分别存放了制作主库和从库所需的全部材料;

Dockerfile

主库镜像的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"]

上述脚本内有详细注释,就不多赘述了,以下三点需要注意:
1. /etc/mysql/extend.conf.d是在my.cnf中定义的,用来存放自定义配置文件的目录,需要创建好,否则mysql启动会报错;
2. 新的docker-entrypoint.sh文件,记得增加可执行权限,如果不加的话,在vmware的ubuntu上可以创建容器成功,在真正的ubuntu电脑上创建容器会失败,提示找不到可执行文件;
3. entrypoint.sh只是个软链接,真正的脚本是docker-entrypoint.sh,官方镜像是这么设置的,在此脚本中和官方保持一致;

接下来,我们看看用来覆盖官方镜像中的my.cnf和docker-entrypoint.sh的文件的具体内容;

配置文件my.cnf

主库和从库的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

容器启动后脚本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

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
  1. 该脚本定义了三个容器:一主二从;
  2. 主库的镜像是bolingcavalry/mysql-master:0.0.1,从库的镜像是bolingcavalry/mysql-slave:0.0.1,都是自制的;
  3. 主库的环境变量MYSQL_REPLICATION_USER、MYSQL_REPLICATION_PASSWORD是用来设置主从同步账号的;
  4. docker-compose.yml所在目录下的master文件夹被映射到容器的/etc/mysql/extend.conf.d目录,这个目录在my.cnf中已经被指定为存放配置文件的目录,所以我们在master文件夹下创建的master.cnf文件会被MySQL识别和加载,此文件中有server id,以及开启bin log的设置,如下:
[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主从三部曲》的终篇;

前文链接

《Docker下MySQL主从三部曲之一:极速体验》

后文链接

《Docker下MySQL主从三部曲之三:binlog日志参数实战》

猜你喜欢

转载自blog.csdn.net/boling_cavalry/article/details/79775617
今日推荐