docker-composeでレプリケーション練習（写経）

[docker\-composeでMaster/Slave構成のMySQLを手に入れる](https://qiita.com/takyam/items/f13bc4a1db0433ffb958)　の写経

- 永続化のところはmasterもtmpfsへ
- `MYSQL_ALLOW_EMPTY_PASSWORD`（実験用には）便利すぎる
- 固定IPを振らないとreplユーザーのネットワークアクセス制限ができない
- レプリケーションをrootからreplユーザーで行うよう変更


# 準備

```
$ ls
docker-compose.yml  master.cnf  slave.cnf  start-slave.sh
```

```yml:docker-compose.yml
version: '3'
services:
  mysql:
    image: mysql:5.7
    ports:
      - "3306:3306"
    tmpfs: /var/lib/mysql
    volumes:
      - ./master.cnf:/etc/mysql/conf.d/my.cnf
    networks:
      db_net:
        ipv4_address: 192.168.192.2
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 1
      TZ: "Asia/Tokyo"
  mysql-slave:
    image: mysql:5.7
    ports:
      - '13306:3306'
    depends_on:
      - mysql
    tmpfs: /var/lib/mysql
    volumes:
      - ./slave.cnf:/etc/mysql/conf.d/my.cnf
      - ./start-slave.sh:/docker-entrypoint-initdb.d/start-slave.sh
    networks:
      db_net:
        ipv4_address: 192.168.192.3
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 1
      TZ: "Asia/Tokyo"

networks:
  db_net:
    driver: bridge
    ipam:
      config:
      - subnet: 192.168.192.0/24
```

```
$ cat master.cnf slave.cnf
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
log-bin=mysql-bin
expire_logs_days=5
server-id=1

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
log-bin=mysql-bin
expire_logs_days=5
server-id=2
read_only=1
```


```
cat start-slave.sh
#!/bin/sh

# depends_onの設定しておけば気にならないけど念の為masterの起動を待つ
while ! mysqladmin ping -h mysql --silent; do
  sleep 1
done

mysql -u root -h mysql -e "CREATE USER 'repl'@'192.168.192.3' IDENTIFIED BY 'slavepass';"
mysql -u root -h mysql -e "GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.192.3';"

# masterをロックする
mysql -u root -h mysql -e "RESET MASTER;"
mysql -u root -h mysql -e "FLUSH TABLES WITH READ LOCK;"

# masterのDB情報をDumpする
# ここでは --all-databases にしてるけど用途に応じて必要なDBだけにしていいと思う
mysqldump -uroot -h mysql --all-databases --master-data --single-transaction --flush-logs --events > /tmp/master_dump.sql
# 特定のDBだけにする場合はこんな感じ(my.cnfのreplica-do-dbも忘れずに設定すること)
# mysqldump -uroot -h mysql データベース名 --master-data --single-transaction --flush-logs --events > /tmp/master_dump.sql

# dumpしたmasterのDBをslaveにimportする
mysql -u root -e "STOP SLAVE;";
mysql -u root < /tmp/master_dump.sql

# masterに繋いで bin-logのファイル名とポジションを取得する
log_file=`mysql -u root -h mysql -e "SHOW MASTER STATUS\G" | grep File: | awk '{print $2}'`
pos=`mysql -u root -h mysql -e "SHOW MASTER STATUS\G" | grep Position: | awk '{print $2}'`

# slaveの開始
mysql -u root -e "RESET SLAVE";
#mysql -u root -e "CHANGE MASTER TO MASTER_HOST='mysql', MASTER_USER='root', MASTER_PASSWORD='', MASTER_LOG_FILE='${log_file}', MASTER_LOG_POS=${pos};"
mysql -u root -e "CHANGE MASTER TO MASTER_HOST='mysql', MASTER_USER='repl', MASTER_PASSWORD='slavepass', MASTER_LOG_FILE='${log_file}', MASTER_LOG_POS=${pos};"
mysql -u root -e "start slave"

# masterをunlockする
mysql -u root -h mysql -e "UNLOCK TABLES;"
```

# 実食

```
$ docker-compose up -d
$ docker-compose exec mysql-slave bash // slaveにログイン
# mysql -u root -e "SHOW SLAVE STATUS\G" // レプリケーションできていること確認
# exit
$ docker-compose exec mysql bash // masterにログイン
# mysql -u root
mysql> CREATE DATABASE users; // usersデータベースを作成
mysql> quit
# exit
$ docker-compose exec mysql-slave bash // 再びslaveにログイン
# mysql -u root -e "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| users              | // 追加されたものが同期されている
+--------------------+
```

# 参考

[mysql \- Docker Hub](https://hub.docker.com/_/mysql/)
[MySQL GTID レプリケーション素振り \- ngyukiの日記](https://ngyuki.hatenablog.com/entry/2018/06/21/210938)
[docker\-composeでMaster/Slave構成のMySQLを手に入れる \- Qiita](https://qiita.com/takyam/items/f13bc4a1db0433ffb958)
[docker\-composeで起動したコンテナにbashで入ったりコマンドを渡す \- Qiita](https://qiita.com/setouchi/items/ebfeefb7d5b129002177)
[MySQLチートシート \- Qiita](https://qiita.com/hryshtk/items/dd69db351bb47f57b4e1)
[MySQL コマンドチートシート　初心者向け \- Qiita](https://qiita.com/yoru722/items/777c0d7a5404a4ef14dd)
[PostgreSQLとMySQLの基本的なコマンドを比較 \- Qiita](https://qiita.com/pugiemonn/items/75870ece3c8476bcb1c8)
[docker\-composeでお手軽mysqlのmaster\-slave構成 \- ウェブエンジニア珍道中](https://www.te-nu.com/entry/2018/07/01/181714)
[日々の覚書: MySQL 8\.0\.3とそれ以降では expire\_logs\_days は非推奨なパラメーターになりました](https://yoku0825.blogspot.com/2018/04/mysql-803-expirelogsdays.html)
[MySQLでバイナリログを定期的に削除するmy\.cnfの設定（expire\_logs\_days） \- ドラあり！\*ドラゴンに挑むアリの物語 \*\* Python使いの日々](http://d.hatena.ne.jp/omiyan/20110128/p1)