Dockerの公式MySQLを触ってみた（初心者）

# ゴール
- マルチバイト対応（日本語が化けないようにする）
- Dockerコンテナを消してもデータを消えないようにする
- おまけ（docker-compose化）※[追記]コメントで指摘頂きましたが、composeを使えばそもそもファイルの置き換えは不要ですね！

# マルチバイト文字対応

デフォルトの文字コードだと日本語が文字化けしてしまうので、UTF-8化してみることにする。
[Dockerの公式MySQLは日本語が文字化けするのでutf8かutf8mb4にしたい](http://unskilled.site/docker%E3%81%AE%E5%85%AC%E5%BC%8Fmysql%E3%81%AF%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%8C%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91%E3%81%99%E3%82%8B%E3%81%AE%E3%81%A7utf8%E3%81%8Butf8mb4%E3%81%AB%E3%81%97/)
に詳しく書かれているので詳細は端折ることにする。

## 手順

文字コードを設定する、mysqld.cnfを公式のDocker Imageから抜き出してコンテナを設定ファイルを書き換えて日本語化する

### Docker Image作成
```
docker run -d --name test -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=testdb mysql:8.0.0
```
testというコンテナ名で作成。作成したコンテナは設定ファイルを取り出すためだけのもので、すぐに削除するので名前はなんでも良い。


※バージョンが異なると、設定ファイルの置き場所が変わることがあるので、
今回は、2017/2/21時点で最新の8.0.0のイメージを利用することにする。

```mysql:8.0.0``` の部分のバージョンタグを削って```mysql```とすると最新のバージョンがDLされる。

### Docker containerから元となるmysqld.cnfを抜き出す

```
mkdir mysql.conf.d
docker cp test:/etc/mysql/mysql.conf.d/mysqld.cnf ./mysql.conf.d/
```

設定ファイルの置き場所

```
/path/to/
└── mysql.conf.d
    └── mysqld.cnf
```

参考ページのDockerイメージとバーションが異なったみたいで、
設定ファイルの場所が変わっていたので、
```docker exec test -it /bin/bash```
を使ってコンテナにsshして設定ファイルの場所を調べました。 　※testはコンテナ名


### 文字コードをUTF-8に書き換え

```mysql:mysqld.cnf
(省略)
[mysqld]
# 以下の1行を追加
character-set-server = utf8
pid-file	= /var/run/mysqld/mysqld.pid
socket		= /var/run/mysqld/mysqld.sock
datadir		= /var/lib/mysql
#log-error	= /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address	= 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# 以下の2行を追加
[client]
default-character-set=utf8
```
※mysql clientの文字コードもutf-8に変更

# 元となるDockerコンテナを削除
```
docker stop test
docker rm test
```

# コンテナ再作成＆起動
```
docker run -d --name mydb -v /path/to/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=db mysql:8.0.0

# コンテナ名：mydb
# rootのパスワード：password
# スキーマ名：db
# ポイント：　-vオプションでホストの任意のパスをコンテナの任意のパスにマウント
```
/path/to/の場所は適宜書き換えください。

## 文字コードの確認

コンテナに接続して文字コードを確認

```
$ docker exec -it mydb bash

# dockerコンテナ側での作業
# mysql -u root -ppassword
mysql> show variables like "chara%";
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)
```

これで、文字コードの変更は完了。

# Dockerコンテナを消してもデータを消えないようにする

## データvolumeの場所を調べる
```
$ docker inspect mydb


(省略)
            {
                "Type": "volume",
                "Name": "b62ce9b9b35e964ad1f34af9dab41522050735b0f174d226a587e47a5f322e25",
                "Source": "/var/lib/docker/volumes/b62ce9b9b35e964ad1f34af9dab41522050735b0f174d226a587e47a5f322e25/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
(省略)
```

```/var/lib/mysql``` がMySQLのデータボリュームだということがわかる。

```
/path/to/
├── mysql.conf.d
└── volume     // ←ホスト側にvolumeディレクトリを作成
```

```
$ docker run -d --name mydb -v /path/to/mysql.conf.d/:/etc/mysql/mysql.conf.d/ -v /path/to/volume/:/var/lib/mysql/ -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=db mysql:8.0.0

# -v /path/to/volume/:/var/lib/mysql オプションを追加
```
-v フラグは複数指定することが可能で、複数の Data Volume をマウントすることができる。


## サンプルデータを登録

```
$ docker exec -it mydb bash

#以下コンテナ側の作業
# mysql -u root -ppassword

mysql>

CREATE SCHEMA IF NOT EXISTS `docker_scheme` DEFAULT 
CHARACTER SET utf8 ;
USE `docker_scheme` ;

DROP TABLE IF EXISTS `docker_scheme`.`students` ;

CREATE TABLE IF NOT EXISTS `docker_scheme`.`students` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(32) NOT NULL DEFAULT '',
  `age` INT NOT NULL DEFAULT 20,
  PRIMARY KEY (`id`),
  INDEX `AGE` (`age` ASC))
ENGINE = InnoDB;

INSERT INTO students(`name`, `age`) VALUES('Tanaka', 21);
```

# コンテナを削除

```
# 停止&削除
docker stop mydb
docker rm mydb

# プロセスが存在しないことを確認
docker ps -a
```

# Dockerコンテナ再作成して、データが保持されているかを確認
上記のdocker runを再実行する

```
# mysql -u root -ppassword

mysql> use docker_scheme;

mysql> select * from students;
+----+--------+-----+
| id | name   | age |
+----+--------+-----+
|  1 | Tanaka |  21 |
+----+--------+-----+
1 row in set (0.00 sec)
````

コンテナを停止してもデータが保持されていることを確認

# おまけ（Docker Compose化）

```docker run```するのにオプションが多くて面倒なので
docker-compose.yamlに記述して簡略化する。

```docker-compose.yaml
# MySQLコンテナ
mysql:
  image: mysql:8.0.0
  container_name: mydb
  volumes:
    - "/path/to/mysql.conf.d/:/etc/mysql/mysql.conf.d/"
    - "/path/to/volume/:/var/lib/mysql/"
  environment:
    - MYSQL_ROOT_PASSWORD=password
```

あとは、
```docker-compose up -d```

すればコンテナが起動する