🌲

DockerでMySQLのMaster/Slave構成

2023/08/18に公開

はじめに

MySQLでMaster/Slaveを構成する方法について紹介します。
Master/Slaveを構成するためには大別してバイナリログGTIDの2つの方法があります。

今回はGTIDを用いてMaster/Slave構成をDockerで構築します。
GTIDの詳しい説明は以下の記事などを確認してください。

https://qiita.com/boro1234/items/797b97fc06e7c688b7b2

環境

実行した環境は以下の通りです。

  • macOS: 13.5
  • MySQL: 8.0

コード

本記事のコードはGitHubにありますので、適宜確認ください。
(本記事には載っていないPHP関連のコードもあります)。

共通

以下のようなディレクトリを想定しています。
MasterとSlaveのMySQLに関するファイルをそれぞれ作成していきます。

.
├── docker
│  └── mysql
│     ├── init_master.sql
│     ├── init_slave.sql
│     ├── master
│     │  └── my.cnf
│     ├── master.Dockerfile
│     ├── slave
│     │  └── my.cnf
│     └── slave.Dockerfile
└── docker-compose.yaml
docker-compose.yaml
  mysql_master:
    container_name: mysql_master
    build:
      context: ./docker/mysql
      dockerfile: master.Dockerfile
    volumes:
      - ./volumes/mysql/master:/var/lib/mysql/
    tty: true
    ports:
      - "3306:3306"
    privileged: true
    platform: linux/amd64
    environment:
      TZ: 'Asia/Tokyo'
    logging:
      driver: json-file
      options:
        max-file: '1'
        max-size: 3m

  mysql_slave:
    container_name: mysql_slave
    build:
      context: ./docker/mysql
      dockerfile: slave.Dockerfile
    volumes:
      - ./volumes/mysql/slave:/var/lib/mysql/
    tty: true
    ports:
      - "3307:3306"
    platform: linux/amd64
    depends_on:
      - mysql_master
    environment:
      TZ: 'Asia/Tokyo'
    logging:
      driver: json-file
      options:
        max-file: '1'
        max-size: 3m

master側

docker/mysql/master.Dockerfile
FROM mysql/mysql-server:8.0.28

RUN touch /var/log/mysql-general.log
RUN chown mysql:mysql /var/log/mysql-general.log
RUN touch /var/log/mysql-error.log
RUN chown mysql:mysql /var/log/mysql-error.log
RUN touch /var/log/mysql-slow.log
RUN chown mysql:mysql /var/log/mysql-slow.log

COPY ./master/ /etc/mysql/
COPY init_master.sql /docker-entrypoint-initdb.d/initialize.sql
docker/mysql/master/my.cnf
[client]
default-character-set=utf8mb4

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
innodb-use-native-aio=0
log_error=/var/log/mysql-error.log
general_log_file=/var/log/mysql-general.log
general_log=1
slow_query_log_file=/var/log/mysql-slow.log
slow_query_log=1
long_query_time=2

# master/slave
server-id=1
# binary-log
log-bin
binlog-format=row
gtid_mode=ON
enforce_gtid_consistency=ON
docker/mysql/init_master.sql
CREATE USER 'zenn_master'@'%' IDENTIFIED WITH mysql_native_password BY 'zenn_master';
GRANT ALL PRIVILEGES ON *.* TO 'zenn_master'@'%';
GRANT REPLICATION SLAVE ON *.* TO 'zenn_master'@'%';
FLUSH PRIVILEGES;

slave側

docker/mysql/master.Dockerfile
FROM mysql/mysql-server:8.0.28

RUN touch /var/log/mysql-general.log
RUN chown mysql:mysql /var/log/mysql-general.log
RUN touch /var/log/mysql-error.log
RUN chown mysql:mysql /var/log/mysql-error.log
RUN touch /var/log/mysql-slow.log
RUN chown mysql:mysql /var/log/mysql-slow.log

COPY ./slave/ /etc/mysql/
COPY init_slave.sql /docker-entrypoint-initdb.d/initialize.sql
docker/mysql/slave/my.cnf
[client]
default-character-set=utf8mb4

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
innodb-use-native-aio=0
log_error=/var/log/mysql-error.log
general_log_file=/var/log/mysql-general.log
general_log=1
slow_query_log_file=/var/log/mysql-slow.log
slow_query_log=1
long_query_time=2

# master/slave
server-id=2
# binary-log
log-bin
binlog-format=row
gtid_mode=ON
enforce_gtid_consistency=ON
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin
read_only
docker/mysql/init_slave.sql
CREATE USER 'zenn_slave'@'%' IDENTIFIED WITH mysql_native_password BY 'zenn_slave';
GRANT ALL PRIVILEGES ON *.* TO 'zenn_slave'@'%';

実行と初期設定

MySQLを以下のコマンドで立ち上げます。

$ docker compose up --build
(...前略)
mysql_slave   | [Entrypoint] MySQL init process done. Ready for start up.
mysql_slave   |
mysql_master  |
mysql_master  | [Entrypoint] MySQL init process done. Ready for start up.
mysql_master  |
mysql_slave   | [Entrypoint] Starting MySQL 8.0.28-1.2.7-server
mysql_master  | [Entrypoint] Starting MySQL 8.0.28-1.2.7-server

立ち上がったことを確認したら、Slave側に入って設定をしていきます。

$ docker exec -it mysql_slave mysql -uzenn_slave -pzenn_slave
mysql> CHANGE MASTER TO MASTER_HOST='mysql_master', MASTER_USER='zenn_master', MASTER_PASSWORD='zenn_master', MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 7 warnings (0.09 sec)
mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.07 sec)

# Master/Slave設定の状態確認
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event # ここ
                  Master_Host: mysql_master
                  Master_User: zenn_master
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 0001e1a2cb18-bin.000003
          Read_Master_Log_Pos: 362
               Relay_Log_File: slave-relay-bin.000002
                Relay_Log_Pos: 592
        Relay_Master_Log_File: 0001e1a2cb18-bin.000003
             Slave_IO_Running: Yes # ここ
            Slave_SQL_Running: Yes # ここ
            (...後略)
            
# 作成直後のデータベース確認
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

Slave_IO_Stateを確認してWaiting for master to send eventと表示されているか、
またSlave_IO_RunningSlave_SQL_Runningの両方が Yes であることを確認します。

これでMaster/Slave構成そのものは完了しています。
Master側に入って正しく動くか確かめてみます。

$ docker exec -it mysql_master mysql -uzenn_master -pzenn_master
# Master側でデータベースを作成する
mysql> CREATE DATABASE zenn_db CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

# Master側で操作後のデータベース確認
# Slave側に反映されているか確認する
# 以下のように反映されていたらOKです。
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| zenn_db            |
+--------------------+

おわりに

レプリケーションにはバイナリログではなくGTIDという方法もあることを初めて知りました。
誰かの参考になれば幸いです。

参考

https://qiita.com/wf-yamaday/items/47434b8312737da25521

GitHubで編集を提案

Discussion