🌲
DockerでMySQLのMaster/Slave構成
はじめに
MySQLでMaster/Slaveを構成する方法について紹介します。
Master/Slaveを構成するためには大別してバイナリログ
とGTID
の2つの方法があります。
今回はGTID
を用いてMaster/Slave構成をDockerで構築します。
GTID
の詳しい説明は以下の記事などを確認してください。
環境
実行した環境は以下の通りです。
- 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_Running
とSlave_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
という方法もあることを初めて知りました。
誰かの参考になれば幸いです。
参考
Discussion