ComposeでサクッとMySQLのレプリケーションを試す
前提
Docker ComposeでMySQLのレプリケーションを試します。マスタ1、スレーブ1のシンプルな構成です。
Docerfileの作成
今回の本質ではないので日本語対応が必要ない方はスキップしていただいて構いません。スキップした場合はdocker-compose.yaml
で直接mysqlの公式イメージを使用してください。
FROM mysql:8.0
RUN microdnf update -y \
&& microdnf install -y glibc-locale-source bash \
&& localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG=ja_JP.UTF-8
ENV LC_ALL=ja_JP.UTF-8
テーブル作成用のsqlと初期設定用のシェルスクリプトを準備する
マスタで使用する、テーブル作成用のsqlを作成します。
CREATE DATABASE IF NOT EXISTS app;
USE app;
CREATE TABLE IF NOT EXISTS sample_table (
id INT AUTO_INCREMENT PRIMARY KEY,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
マスタで使用する、レプリケーション用ユーザを設定するシェルスクリプト作成します。環境変数を使用したいためsqlではなくシェルスクリプトを使用することにします。
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "CREATE USER '$REPLICA_USER'@'%' IDENTIFIED BY '$REPLICA_PASSWORD';"
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "GRANT REPLICATION SLAVE ON *.* TO '$REPLICA_USER'@'%';"
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "FLUSH PRIVILEGES;"
スレーブで使用する、初期設定用のシェルスクリプトを作成します。
はじめに、CHANGE REPLICATION SOURCE TO
でマスタを指定します。MySQL 8.0.23以降ではCHANGE MASTER TO
は非推奨となりました。
次にマスタのデータをダンプし、スレーブ側で読み込みます。--master-data=1
を指定することでSOURCE_LOG_FILE (MASTER_LOG_FILE)
、SOURCE_LOG_POS (MASTER_LOG_POS)
を手動で指定する必要がなくなります。
最後にSTART REPLICA
でレプリケーションを開始します。こちらもMySQL 8.0.22からSTART SLAVE
が非推奨になりました。
echo "Starting the MySQL slave initialization script..."
# Execute the command to set up the slave
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "CHANGE REPLICATION SOURCE TO SOURCE_HOST='$MASTER_HOST', SOURCE_PORT=$MASTER_PORT, SOURCE_USER='$REPLICA_USER', SOURCE_PASSWORD='$REPLICA_PASSWORD', GET_MASTER_PUBLIC_KEY=1;"
if [ $? -ne 0 ]; then
echo "Error: Unable to set up the slave server."
exit 1
fi
echo "Successfully set up the slave server."
# Dump the master database
mysqldump -u $MASTER_USER -h $MASTER_HOST -P $MASTER_PORT -p$MASTER_PASSWORD --all-databases --single-transaction --routines --triggers --events --master-data=1 > /tmp/master_dump.sql
if [ $? -ne 0 ]; then
echo "Error: Unable to dump the master database."
exit 1
fi
echo "Successfully dumped the master database."
# Import the dump into the slave
mysql -u root -p$MYSQL_ROOT_PASSWORD < /tmp/master_dump.sql
if [ $? -ne 0 ]; then
echo "Error: Unable to import the dump into the slave."
exit 1
fi
echo "Successfully imported the dump into the slave."
mysql -u root -p$MYSQL_ROOT_PASSWORD -e "START REPLICA;"
if [ $? -ne 0 ]; then
echo "Error: Unable to start the slave."
exit 1
fi
echo "Successfully started the slave server."
docker-compose.yamlの設定
上記の各種設定ファイルを使用するようdocker-compose.yamlを構成します。一部省略している箇所があります。スレーブはマスタのヘルスチェックが通ることを確認してから起動するよう設定しておきます。
services:
db-master:
container_name: ${COMPOSE_PROJECT_NAME}_master
build:
context: ./mysql
dockerfile: Dockerfile
environment:
MYSQL_ROOT_PASSWORD: password
...
volumes:
- ./mysql/master/init:/docker-entrypoint-initdb.d
- ./mysql/master/conf.d:/etc/mysql/conf.d
- ./volume/master/mysql:/var/lib/mysql
- ./volume/master/log/mysql:/var/log/mysql
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD" ]
interval: 5s
timeout: 30s
retries: 10
start_period: 120s
db-slave:
container_name: ${COMPOSE_PROJECT_NAME}_slave
build:
...
environment:
...
depends_on:
db-master:
condition: service_healthy
volumes:
...
healthcheck:
...
動作を試す
マスタにクエリを発行したのち、スレーブでもデータが正しく反映されていることを確認します。
まとめ
今回使用したコードは以下で公開しています。
フォロー、X(Twitter)フォローもよろしくお願いいたします。
Discussion