DockerでMySQL複数バージョンを共存させる

MacローカルでMySQL5.6.xとMySQL5.7.xを同時に起動して、アプリケーション毎に接続するバージョンのすみ分けができるようにする。

[Multiple MySQL Versions with Homebrew](https://gist.github.com/benlinton/d24471729ed6c2ace731)とかでHomebrewで両バージョンをインストールして `brew switch` で切り替える方法でも運用してたが、切り替えやログファイル削除が面倒だったり、Rails -> MySQLのアクセスで不具合が発生したりと面倒だった。

それとDockerを使いたかったので今回はDockerでやってみた。

# 前提条件

- macOS Sierra 10.12.6
- [Docker Toolbox](https://docs.docker.com/toolbox/toolbox_install_mac/)がインストールされていること
- Macローカルで， `mysql` がインストールされていること (ローカルMacからコマンドから接続するのに必要)


# Dockerセットアップ

## Dockerホスト作成

```bash
$ docker-machine create --driver virtualbox dev
```

## 起動確認

```bash
$ docker-machine ls
NAME      ACTIVE   URL          STATE     URL                         SWARM   DOCKER    ERRORS
dev       *        virtualbox   Running   tcp://192.168.99.100:2376           v1.11.1
```

# MySQLセットアップ

## Docker公式のMySQLイメージを使用

バージョンを指定せずに `docker pull mysql` だと最新版が自動的に選ばれる。

```bash
$ docker pull mysql:5.7
$ docker pull mysql:5.6
```

## イメージ確認

```bash
$ docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
mysql                           5.7                 sha256:2fd13        2 weeks ago         378.4 MB
mysql                           5.6                 sha256:2c096        2 weeks ago         329 MB
```

## コンテナを起動する

バージョン毎にHost OS ↔ Container 間のポートを変更して起動する。

```bash
$ docker run --name mysql5.6 -p 3307:3306 -e MYSQL_DATABASE=test -e MYSQL_USER=root -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
$ docker run --name mysql5.7 -p 3308:3306 -e MYSQL_DATABASE=test -e MYSQL_USER=root -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
```

**追記: docker run するときに，文字セットを指定した方がよい**

![image.png](https://qiita-image-store.s3.amazonaws.com/0/31862/0a933bb9-75c5-c80c-40c9-cd909502264f.png)
[Docker公式イメージのMySQLで文字コードを指定する](https://qiita.com/neko-neko/items/de8ea13bbad32140de87)

デフォルトだと `latin1` が設定されてしまい，意図しないところで文字化けが発生したりする可能性がある．
例えば `mysqldump` で作成したダンプに日本語が含まれていると `????` に変換されてしまう．
その場合は `--default-character-set=utf8` をつけて実行すれば回避できるが，コンテナ実行時に指定しておく方がよいだろう．

```
mysql> status
--------------
mysql  Ver 8.0.11 for osx10.13 on x86_64 (Homebrew)

Connection id:		2
Current database:
Current user:		root@192.168.99.1
SSL:			Cipher in use is DHE-RSA-AES256-SHA
Current pager:		stdout
Using outfile:		''
Using delimiter:	;
Server version:		5.7.22 MySQL Community Server (GPL)
Protocol version:	10
Connection:		192.168.99.100 via TCP/IP
Server characterset:	utf8mb4
Db     characterset:	utf8mb4
Client characterset:	utf8mb4
Conn.  characterset:	utf8mb4
TCP port:		3307
Uptime:			14 sec

Threads: 1  Questions: 5  Slow queries: 0  Opens: 105  Flush tables: 1  Open tables: 98  Queries per second avg: 0.357
--------------
```

## コンテナの起動・接続確認

各バージョンのコンテナが起動していればOK

```bash
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
caf0cf83cf42        mysql:5.7           "docker-entrypoint.sh"   26 hours ago        Up 5 hours          0.0.0.0:3308->3306/tcp   mysql5.7
dada0336b90a        mysql:5.6           "docker-entrypoint.sh"   27 hours ago        Up 6 hours          0.0.0.0:3307->3306/tcp   mysql5.6
```

Macから各コンテナ毎に接続できることを確認する。
`docker-machine ip dev` はDockerホストのIPアドレスを返す。

```bash
$ mysql -h$(docker-machine ip dev) -P3307 -uroot -p123456
$ mysql -h$(docker-machine ip dev) -P3308 -uroot -p123456
```

MySQLコンソールが立ち上がるのでDB/Table/Userの作成なども普通にできる。

# コンテナ内のDBに対してSQLファイルを実行する

コンテナIPやポートを指定して `.sql` ファイルを実行することもできる。

```bash
$ mysql -u root -p <DATABASE_NAME> -P <PORT> -h$(docker-machine ip dev) < ~/path/to/file.sql
```