• 搜索
  • 夜间模式
    ©2026  依刻学习 Theme by OneBlog

    依刻学习博客

    搜索
    标签
  • 首页>
  • 学习的一天>
  • 正文
  • mysql主从自动容器化(1) 部署

    2025年02月26日 7 阅读 0 评论 5807 字

    环境

    服务版本
    centos7.9
    mysql5.7
    docker26.1.4
    docker-compose2.27.1

    使用docker-compose结合脚本进行自动化部署mysql一主一从
    主节点即master节点容器
    从节点即slave节点容器

    '双主双从'等待未来博客

    思路

    首先理清一般非容器化mysql主从部署思路:

    1. 在多主机上安装mysql(统一版本)
    2. 修改配置文件(区分master与slave)
    3. 主节点需要创建复制用户并授权,进行测试
    4. 从节点需要指定主节点并开启复制线程

    但是容器化就要有N个问题,主要集中在3,4点上

    1. 如何保证主节点先于从节点开启?
    2. 如何从主节点容器获取binlog的文件与断点?
    3. 如何非交互的使用mysql?
    4. 如何进行mysql初始化?

    解答:
    1.如何保证主节点先于从节点开启?
    这个问题如果单独使用dockerfile或直接docker启动其实没什么问题,只要先启动master容器就行了,但是如果使用docker-compose呢?我的第一个想法就是使用depends_on,salve容器依赖master容器不就行了吗?那就太easy,不会放这里了,确实可以使用depends_on设置优先级,但是docker-compose启动了容器不代表服务已经启动了!
    举个简单的例子,如果docker运行比较多就会发现有的容器刚启动还没ps就挂了,有的启动后需要等一会才挂掉,为什么不直接挂断?这是因为容器虽然启动了,但是服务还正在启动,然后发现启动不了,容器就挂了
    docker-compose这里也是一样,depends_on只能设置master优先启动,但此时服务可能正在启动,此时slave如果直接设置复制change master..会直接报错(经测试,即使设置了depends_on,master服务启动也比slave服务慢!)
    实际上需要的不是master容器先于slave容器启动,而是master的mysql服务先于slave的mysql服务启动,我想到的最简单的方法就是在slave的初始化脚本中使用sleep,这样就可以强制salve的mysql服务启动后于master的mysql服务启动

    补:仅使用depends不能保证服务完全启动,只能保证启动顺序,但是depends_on是可以设置需要被依赖容器完全启动才启动依赖容器

    2.如何从主节点获取binlog的文件名与断点并传入从节点?
    通过mysql的-h可以通过容器名实现跨节点的登录mysql,然后使用show master status结合三剑客过滤出FILE与POSTION字段,这样就可以直接在从节点直接获取binlog的文件名与断点

    3.如何非交互的使用mysql?
    通过mysql的-e参数可以实现非交互式的操作mysql,需要注意的是,如果需要连续输入多个命令可以使用双引号将SLQ扩起来,这样就不用使用多个mysql命令重复登录操作就可以一次实现操作了

    4.如何进行mysql初始化?
    使用mysql的初始化脚本,初始化脚本docker-entrypoint.sh会执行docker-entrypoint-initdb.d中的脚本,只要将脚本传入其中即可作为初始化脚本

    最终使用文件

    • master的配置文件my1.cnf
    • slave的配置文件my2.cnf
    • docker-compose.yml
    • 初始化脚本init.sh
    • 启动命令脚本START

    目录层级如下

    实现

    1.master的配置文件my1.cnf

    [mysqld]
    datadir=/var/lib/mysql
    symbolic-links=0
    log-error=/var/log/mysqld.log
    pid-file=/var/run/mysqld/mysqld.pid
    
    server_id=1
    #开启binlog日志
    log_bin=mysql-bin.log
    binlog_format=ROW              
    max_binlog_size=500M              
    expire_logs_days=7         
    slave_skip_errors=1062     
    log-slave-updates=1         
    auto-increment-increment=2 
    auto-increment-offset=1
    replicate-ignore-db=mysql
    replicate-ignore-db=sys
    replicate-ignore-db=information_schema
    replicate-ignore-db=performance_schema
    

    2.slave的配置文件my2.cnf

    [mysqld]
    datadir=/var/lib/mysql
    symbolic-links=0
    log-error=/var/log/mysqld.log
    pid-file=/var/run/mysqld/mysqld.pid
    
    #server_id必须与master不同
    server_id=2
    #开启只读
    read_only = 1

    3.docker-compose.yml

    version: "3.8"
    services:
      master:
        image: mysql:5.7
        container_name: mysql_master
        #build: 
        restart: always
        ports:
        - 3306
        volumes:
        - data1:/var/lib/mysql
        - /app/docker/mysql_cluster/my1.cnf:/etc/mysql/conf.d/my.cnf
        - /app/docker/mysql_cluster/init.sh:/docker-entrypoint-initdb.d/init.sh
        networks:
        - mysql_cluster
        env_file:
        - env
        environment:
        - ROLE=master
        #command:
    
      slave:
        image: mysql:5.7
        container_name: mysql_slave
        #build: 
        restart: always
        ports:
        - 3306
        #注意,depends_on是可以实现完全服务启动再往后执行的,本次使用sleep(脚本中)实现
        depends_on:
        - master
        volumes:
        - data2:/var/lib/mysql
        - /app/docker/mysql_cluster/my2.cnf:/etc/mysql/conf.d/my.cnf
        - /app/docker/mysql_cluster/init.sh:/docker-entrypoint-initdb.d/init.sh
        networks:
        - mysql_cluster
        env_file:
        - env
        #传入ROLE与MASTER
        environment:
        - ROLE=slave
        - MASTER=mysql_master
        #command:
    
    networks:
      mysql_cluster:
        driver: bridge
    
    volumes:
      data1: {}
      data2: {}

    4.初始化脚本init.sh(适用于主+从节点)

    #!/bin/bash
    #需要传入变量ROLE(本机身份,用于判断),MASTER(从节点需要传入用于指定主节点容器名)
    
    #错误判断
    function test_order {
      if [ $? -ne 0 ]; then
        echo "命令执行错误" 
        exit 1
      fi
    }
    
    function MASTER {
      #创建用户(在没有传入MYSQL_USER和MYSQL_PASSWORD时启用)
      #CREATE_SQL="create user "slave"@'%' identified by '123';"
      #授权复制用户
      GRANT_SQL="grant replication slave on *.*  to "${MYSQL_USER}"@'%';"
      #刷新权限
      FLUSH_SQL="flush privileges;"
      mysql -u 'root' -p"${MYSQL_ROOT_PASSWORD}" -e "${GRANT_SQL}  ${FLUSH_SQL}"
      test_order
    }
    
    function SLAVE {
      sleep 10
      SHOW_STATUS_SQL1="SHOW MASTER STATUS;"
      FILE="$(mysql -u'root' -p"${MYSQL_ROOT_PASSWORD}" -h ${MASTER} -e"${SHOW_STATUS_SQL1}"|grep mysql|awk '{print $1}')" &>>/dev/stdout
      POSITION="$(mysql -u'root' -p"${MYSQL_ROOT_PASSWORD}" -h ${MASTER} -e"${SHOW_STATUS_SQL1}"|grep mysql|awk '{print $2}')" &>>/dev/stdout
      #从节点开启复制
      CHANGE_MASTER_SQL="change master to master_host='${MASTER}',master_user='${MYSQL_USER}',master_password='${MYSQL_PASSWORD}',master_log_file='${FILE}',master_log_pos=${POSITION};"
      START_SLAVE="start slave;"
      #指定主节点
      mysql -u 'root' -p"${MYSQL_ROOT_PASSWORD}" -e "${CHANGE_MASTER_SQL} ${START_SLAVE}" 
      test_order
    }
    
    #角色为master
    if [ "${ROLE}" = "master" ]; then 
      MASTER
    #角色为slave
    elif [ "${ROLE}" = "slave" ]; then
      SLAVE
    else
      exit 1
    fi

    5.环境变量文件env(通用变量,主+从挂载)

    #env.txt
    MYSQL_ROOT_PASSWORD=MyStr0ngP@ssw0rd!
    MYSQL_USER=slave
    MYSQL_PASSWORD=123
    

    6.启动命令脚本START

    #!/bin/bash
    docker compose down &>/dev/null
    docker volume rm mysql_cluster_data1
    docker volume rm mysql_cluster_data2
    docker compose up -d 
    docker ps

    7.一点注意事项

    • master节点需要传入ROLE用于判断角色
    • slave节点需要传入ROLE用于判断角色,需要传入MASTER用于确定master节点的容器名
    • 如果执行出问题,可以尝试进入容器手动执行init.sh初始化脚本

    启动START脚本即可

    最终总结

    搭了两天才搭起来,一方面是mysql好久没搭过主从,另一方面是之前没有接触过mysql容器的自动化,几乎都是花时间在脚本的调错上

    配置过程中的错误参考mysql主从自动容器化(2) 错误
    已推送至gitee仓库.可直接通过gitee仓库下载配置文件 my-sqlauto-replica仓库

    本文著作权归作者 [ wymm ] 享有,未经作者书面授权,禁止转载,封面图片来源于 [ 互联网 ] ,本文仅供个人学习、研究和欣赏使用。如有异议,请联系博主及时处理。
    取消回复

    发表留言
    回复

    Copyright©2026  All Rights Reserved.  Load:0.031 s
    Theme by OneBlog V3.6.5
    夜间模式

    开源不易,请尊重作者版权,保留基本的版权信息。