本番環境は MySQL のマスターとリードレプリカのスレーブで構成されているものの、ローカル環境はシングル構成なこと、よくあります。
そういうとき、レプリケーション遅延が原因による不自然な表示・・不具合が生じることがあったりするので、docker-compose なローカル環境でもサクッとレプリケーション環境を用意する方法。
Docker Hub のオフィシャルの MySQL イメージならコンテナの /docker-entrypoint-initdb.d/ にシェルスクリプトを置いておけば初回開始時に自動的に実行されるので、これを利用します。
docker-compose.yml
環境変数 MYSQL_REPLICATION_USER
MYSQL_REPLICATION_PASSWORD
でレプリケーションのユーザー名・パスワードを指定します。MYSQL_REPLICATION_HOST
でマスターのホストを指定しますがこれはスレーブでのみ設定します。
version: '3.7' services: mysql-master: image: mysql:8 command: - --default_authentication_plugin=mysql_native_password - --gtid_mode=ON - --enforce_gtid_consistency=ON - --relay-log=relay-bin - --server_id=1 environment: &environment TZ: Asia/Tokyo MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_DATABASE: test MYSQL_USER: test MYSQL_PASSWORD: pass MYSQL_REPLICATION_USER: repl MYSQL_REPLICATION_PASSWORD: pass volumes: - ./init.sh:/docker-entrypoint-initdb.d/init.sh:ro mysql-slave: image: mysql:8 depends_on: - mysql-master command: - --default_authentication_plugin=mysql_native_password - --gtid_mode=ON - --enforce_gtid_consistency=ON - --relay-log=relay-bin - --server_id=2 environment: <<: *environment MYSQL_REPLICATION_HOST: mysql-master volumes: - ./init.sh:/docker-entrypoint-initdb.d/init.sh:ro
init.sh
コンテナの /docker-entrypoint-initdb.d/init.sh
にマウントされるスクリプトです。レプレーションユーザーを作成したり、スレーブを開始したりします。
オフィシャルの MySQL イメージだと entrypoint でユーザーを作成したりデータベースを作成したりいろいろ行われているので、そのままだとレプリケーションの開始後に更新が競合します。
なので、一通り共通の準備が終わったところで RESET MASTER
でバイナリログをふっとばします。
#!/bin/bash if [ -v MYSQL_REPLICATION_USER -a -v MYSQL_REPLICATION_PASSWORD ]; then mysql -u root -v mysql <<SQL CREATE USER '$MYSQL_REPLICATION_USER'@'%' IDENTIFIED BY '$MYSQL_REPLICATION_PASSWORD'; GRANT REPLICATION SLAVE ON *.* TO '$MYSQL_REPLICATION_USER'@'%'; SQL fi mysql -u root -v mysql <<SQL RESET MASTER; SQL if [ -v MYSQL_REPLICATION_USER -a -v MYSQL_REPLICATION_PASSWORD -a -v MYSQL_REPLICATION_HOST ]; then mysqladmin ping --wait=5 -h "$MYSQL_REPLICATION_HOST" mysql -u root -v <<SQL CHANGE MASTER TO MASTER_HOST = '$MYSQL_REPLICATION_HOST', MASTER_USER = '$MYSQL_REPLICATION_USER', MASTER_PASSWORD = '$MYSQL_REPLICATION_PASSWORD', MASTER_AUTO_POSITION = 1, MASTER_DELAY = 10; START SLAVE; SQL fi
動作確認
docker-compose up -d # レプリケーション状態 -> Slave_IO_Running と Slave_SQL_Running ともに Yes docker-compose exec mysql-slave mysql -e 'show slave status \G' # マスターにテーブルを作ってデータを入れる docker-compose exec mysql-master mysql test -e 'create table t (id int not null primary key)' docker-compose exec mysql-master mysql test -e 'insert into t values (1)' # レプリケーション状態 -> Retrieved_Gtid_Set や Executed_Gtid_Set がちょっと進む docker-compose exec mysql-slave mysql -e 'show slave status \G' # レプリケーションされたデータが表示される docker-compose exec mysql-slave mysql test -e 'select * from t'