Administrator
发布于 2023-04-15 / 356 阅读 / 0 评论 / 0 点赞

docker compose 构建mysql 数据主从

参考文章地址

目录结构

.
├── build.sh
├── docker-compose.yml
└── init
├── master
│ └── master.sh
└── slave
└── slave.sh

创建文件

build_databases/docker-compose.yml

version: '3'
services:
  master:
    image: mysql:8.0.28
    container_name: mysql-master # 容器名称
    # platform: "linux/amd64" # 苹果m1适用,其他win or linux注释此行
    ports:
      - '33069:3306' # 主库映射ip
    restart: always
    hostname: mysql-master
    environment:
      MYSQL_ROOT_PASSWORD: "123456" # 超级账号密码
      MASTER_SYNC_USER: "sync_admin" # 给从库创建连接用户名
      MASTER_SYNC_PASSWORD: "123456" # 给从库创建连接密码
	  ALLOW_HOST:  "%"
      TZ: "Asia/Shanghai"
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: 50m
    logging:
      options:
        max-file: '1'
        max-size: '128k'
    command:
      - "--server-id=1"
      - "--character-set-server=utf8mb4"
      - "--collation-server=utf8mb4_unicode_ci"
      - "--log-bin=mysql-bin"
      - "--sync_binlog=1"
      - "--binlog-ignore-db=mysql"
      - "--binlog-ignore-db=sys"
      - "--binlog-ignore-db=performance_schema"
      - "--binlog-ignore-db=information_schema"
      - "--sql_mode=NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES"
    volumes:
      - ./init/master/master.sh:/docker-entrypoint-initdb.d/steup.sh
      - ./data/master:/var/lib/mysql
    networks:
      dev_compose_env:
        ipv4_address: 172.29.0.6 # 定义容器具体ip
  slave:
    image: mysql:8.0.28
    container_name: mysql-slave
    # platform: "linux/amd64" # m1适用,其他win or linux注释此行
    ports:
      - '33076:3306' # 从库映射ip
    restart: always
    hostname: mysql-slave
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
      SLAVE_SYNC_USER: "sync_admin"
      SLAVE_SYNC_PASSWORD: "123456"
      MASTER_HOST: "172.29.0.6"
      ALLOW_HOST:  "%"
      TZ: "Asia/Shanghai"
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: 50m
    logging:
      options:
        max-file: '1'
        max-size: '128k'
    depends_on:
	  # 等待主库容器启动再启动该容器
	  - master
    command:
      - "--server-id=2"
      - "--character-set-server=utf8mb4"
      - "--collation-server=utf8mb4_unicode_ci"
      - "--sql_mode=NO_AUTO_VALUE_ON_ZERO,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,PIPES_AS_CONCAT,ANSI_QUOTES"
    volumes:
      - ./init/slave/slave.sh:/docker-entrypoint-initdb.d/steup.sh
      - ./data/slave:/var/lib/mysql
    networks:
      dev_compose_env:
        ipv4_address: 172.29.0.7 # 定义容器具体ip
networks:
  dev_compose_env:
    # 创建网络组
    ipam:
      config:
        - subnet: 172.29.0.0/16 # 指定静态网段

build_databases/init/master/master.sh

#!/bin/bash
# 此脚本主要是根据环境变量,创建出用于主从同步的用户。关于为什么要创建出master,slave脚本,是为了区分master和slave环境,因为只要把sql和sh文件放到master目录下面,master在第一次初始化的时候,会自动执行里面的文件内容

#定义用于同步的用户名
echo  " --------------------------------- 运行主库配置 ----------------------------------- "

#定义用于同步的用户密码
MASTER_SYNC_USER=${MASTER_SYNC_USER}
MASTER_SYNC_PASSWORD=${MASTER_SYNC_PASSWORD}

#定义运行登录的host地址
ALLOW_HOST=${ALLOW_HOST}

#管理员账号密码
MYSQL_USER="root"
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}

#定义创建账号的sql语句
CREATE_USER_SQL="CREATE USER '$MASTER_SYNC_USER'@'$ALLOW_HOST' IDENTIFIED BY '$MASTER_SYNC_PASSWORD';"

#定义赋予同步账号权限的sql,这里设置两个权限,REPLICATION SLAVE,属于从节点副本的权限,REPLICATION CLIENT是副本客户端的权限,可以执行show master status语句
GRANT_PRIVILEGES_SQL="GRANT SELECT,REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO '$MASTER_SYNC_USER'@'$ALLOW_HOST';"

#定义刷新权限的sql
FLUSH_PRIVILEGES_SQL="FLUSH PRIVILEGES;"

#执行sql
mysql -u$MYSQL_USER  -p$MYSQL_ROOT_PASSWORD  -e  "$CREATE_USER_SQL  $GRANT_PRIVILEGES_SQL  $FLUSH_PRIVILEGES_SQL"

echo  " --------------------------------- 运行主库配置 ----------------------------------- "

build_databases/init/slave/slave.sh

#!/bin/bash
# slave主要是去master查询最新的pos位置和binlog文件名称,然后创建同步需要的相关信息,然后执行start slave;

echo  " --------------------------------- 运行从库配置 ----------------------------------- "

#管理员账号密码
MYSQL_USER="root"
MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD}"

#定义连接master进行同步的账号密码
SLAVE_SYNC_USER="${SLAVE_SYNC_USER}"
echo  "master进行同步的账号:$SLAVE_SYNC_USER"
SLAVE_SYNC_PASSWORD="${SLAVE_SYNC_PASSWORD}"
echo  "master进行同步的账号密码:$SLAVE_SYNC_PASSWORD"

#定义连接master数据库host地址
MASTER_HOST="${MASTER_HOST}"
echo  "master数据库host地址:$MASTER_HOST"

echo  "等待主库启动,延迟60秒"
#等待主库启动,睡眠等待
sleep 60
echo  "等待完成,继续执行任务...."

#连接master数据库,查询二进制数据,并解析出logfile和pos,这里同步用户要开启 REPLICATION CLIENT权限,才能使用SHOW MASTER STATUS;
RESULT=$(mysql -u"$SLAVE_SYNC_USER" -h$MASTER_HOST  -p"$SLAVE_SYNC_PASSWORD" -e "SHOW MASTER STATUS;" | grep -v grep | tail -n +2  | awk '{print $1,$2}')

#解析出logfile
LOG_FILE_NAME=$(echo  $RESULT  | grep -v grep | awk '{print $1}')

#解析出pos
LOG_FILE_POS=$(echo  $RESULT  | grep -v grep | awk '{print $2}')
echo  "logfile:$LOG_FILE_NAME"
echo  "pos:$LOG_FILE_POS"

#设置连接master的同步相关信息
SYNC_SQL="CHANGE MASTER TO MASTER_HOST='$MASTER_HOST',MASTER_USER='$SLAVE_SYNC_USER',MASTER_PASSWORD='$SLAVE_SYNC_PASSWORD',MASTER_LOG_FILE='$LOG_FILE_NAME',MASTER_LOG_POS=$LOG_FILE_POS;"

echo  "连接master的同步相关指令:$SYNC_SQL"

#开启同步
START_SYNC_SQL="start slave;"

#查看同步状态
STATUS_SQL="show slave status\G;"
mysql -u$MYSQL_USER  -p$MYSQL_ROOT_PASSWORD  -e  "$SYNC_SQL  $START_SYNC_SQL  $STATUS_SQL"

echo  " --------------------------------- 运行从库配置 ----------------------------------- "

build_databases/build.sh

#!/bin/bash
# 运行构建
# sh ./build.sh
# 处理shell权限

chmod +x  ./master/master.sh
chmod +x  ./slave/slave.sh

docker compose  up  -d

踩坑记录

  1. /docker-entrypoint-initdb.d初始shell不执行,如果需要创建用户需要避开创建root,否则初始shell中创建root用户失败导致shell执行出错而退出。注意查看shell执行时候的报错,docker compose控制台错误信息不太明显,注意查看ERROR内容是否与指定初始化shell脚本有关系并及时处理。
  2. /bin/sh: 1: docker-compose: Permission denied,初始shell执行权行不足,映射shell会映射权限,需要给予对应的shell脚本权限,参考build_databases/build.sh
  3. 从库未成功开启主从,检查发现未获取到master binlog信息,检查发现主库容器binlog开启成功,考虑是从库脚本执行到检查时候,主库还未开启binlog,未验证编排文件中depends_on是否影响,在slave.sh中获取binlog信息的位置增加了延时。重新编排验证通过。