DockerでMySQLを始める

[link-1]: https://hub.docker.com/_/mysql "Docker"
[link-2]: https://dev.mysql.com/doc/refman/8.0/en/tutorial.html "MySQL Docs"
## はじめに
MySQLの勉強を始める時に環境構築が大変だったので、Dockerを使うことにしました。
Dockerを使うと、ホストの環境を汚すことなくMySQLの環境を作れるのでおすすめです。
本記事は、Docker Desktopがインストールされている前提で書いています。

## MySQLイメージ
Dockerコンテナ上で作ったデータは、コンテナを削除するとなくなってしまいます。データを永続化させるため、ボリュームを使います。
```docker
docker volume create test_mysql
```
このボリュームをマウントして、コンテナを作ります。
以下のコマンドで、`your-password`のところには任意のパスワードを書いてください。MySQLサーバーへ接続するときに使います。
また、MySQLコンテナは通常、データを`/var/lib/mysql`ディレクトリに保存します。
`target`属性を他のディレクトリに変えると、データが永続化されないのでご注意ください。
```docker
docker run --name mysql1 --mount type=volume,source=test_mysql,target=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=your-password -d mysql:latest
```
コンテナが作られるので、コンテナの中に入ります。
```docker
docker exec -it mysql1 bash
```
コンテナ内で以下のコマンドを打つと、MySQLサーバーへ接続されます。
パスワードを要求されるので、コンテナを作ったときに設定したパスワードを入力します。
```
mysql -p
```

## データベース、テーブルの作成
[MySQLチュートリアル][link-2]の中から、データベースとテーブルの作成部分だけ抜き出しています。
MySQLクライアントに入力してデータベースを作ります。
ちなみに、メナジェリー(menagerie)とは、展示目的で飼育されている動物のコレクションのことです。
```sql
mysql> CREATE DATABASE menagerie;
mysql> USE menagerie
```
`USE menagerie`でデータベースにアクセスできます。このとき、最後にセミコロンが要らないので注意してください。
データベースにアクセスできたら、`pet`テーブルを作ります。
```sql
mysql> CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);
```


## データのロード
`pet`テーブルにデータをロードします。公式のチュートリアルにしたがって、以下のテキストファイルをロードすることにします。
```:pet.txt
Fluffy	Harold	cat	f	1993-02-04	\N
Claws	Gwen	cat	m	1994-03-17	\N
Buffy	Harold	dog	f	1989-05-13	\N
Fang	Benny	dog	m	1990-08-27	\N
Bowser	Diane	dog	m	1979-08-31	1995-07-29
Chirpy	Gwen	bird	f	1998-09-11	
Whistler	Gwen	bird	\N	1997-12-09	
Slim	Benny	snake	m	1996-04-29	
```

`pet.txt`をコンテナの中にコピーします。新しいターミナルを開いてください。
`docker cp`コマンドでコピーできますが、コピーするときにはコンテナIDが必要なので、`docker ps`でコンテナIDを確認します。
ファイルをコピーする場所に特段の指定はありませんが、ここでは一時ディレクトリにコピーします。
```docker
docker ps
docker cp <path>/pet.txt <CONTAINER ID>:/tmp
```

MySQLではセキュリティ上の理由から、コンテナの中のローカルファイルをロードできないようになっています。以下の記事を参考にして、一時的にローカルファイルをロードできるように設定を変更します。

https://qiita.com/chibatty/items/cc72fbf1c98a8c2b7bdc

まずはMySQLのデータベースに接続しているターミナルに切り替えて、接続を切ります。
```sql
mysql> QUIT
```
もう一度MySQLに接続します。このときに、クライアント側の`--local-infile`をONにします。
```
mysql -p menagerie --local-infile=ON
```
上記の`menagerie`はパスワードではなく、先ほど作ったデータベースの名前です。
続いて、一時的に`local_infile`変数をONにします。
```sql
mysql> SET GLOBAL local_infile=ON;
```
これでローカルファイルをロードできるようになります。ロードした後は変数の値を元に戻しておきます。
```sql
mysql> LOAD DATA LOCAL INFILE '/tmp/pet.txt' INTO TABLE pet SET death=NULLIF(death, 0);
mysql> SET GLOBAL local_infile=OFF;
```
ここで、日付型にNULLを入れるとき、上記のように`NULLIF`が必要でした。
`pet`テーブルの中身を確認すると、ロードできていることが確認できました。
```sql
mysql> SELECT * FROM pet;
```
```:実行結果
+----------+--------+---------+------+------------+------------+
| name     | owner  | species | sex  | birth      | death      |
+----------+--------+---------+------+------------+------------+
| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |
| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |
| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |
| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |
| Bowser   | Diane  | dog     | m    | 1979-08-31 | 1995-07-29 |
| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |
| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |
| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |
+----------+--------+---------+------+------------+------------+
8 rows in set (0.00 sec)
```

## データが永続されているかの確認
前節まででテーブルの作成までできました。ここでは、コンテナを削除してもデータベースが残っているかを確認します。
まずはMySQLデータベースおよびコンテナとの接続を切ります。MySQLでは`QUIT`、Dockerコンテナでは`exit`コマンドで接続を切ることができます。
```sql
mysql> QUIT
```
```docker
bash-5.1# exit
```
`docker ps`コマンドでコンテナIDを確認して、コンテナを削除してみましょう。
```docker
docker ps
docker stop <CONTAINER ID>
docker rm <CONTAINER ID>
```
もう一度`docker ps`コマンドを打つと、コンテナが削除されていることが確認できます。さて、もう一度新しくコンテナを作ってみます。
わかりやすさのため、コンテナ名を`mysql2`に変えています。その他は同じです。
```docker
docker run --name mysql2 --mount type=volume,source=test_mysql,target=/var/lib/mysql -e MYSQL_ROOT_PASSWORD=your-password -d mysql:latest
docker exec -it mysql2 bash
```
コンテナの中に入ったら、再びMySQLに接続します。
```
mysql -p
```
データベースの一覧を確認すると、`menagerie`が残っていることがわかります。
```sql
mysql> SHOW DATABASES;
```
```:実行結果
+--------------------+
| Database           |
+--------------------+
| information_schema |
| menagerie          |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)
```
また、テーブルも残っています。
```sql
mysql> USE menagerie
mysql> SHOW TABLES;
```
```:実行結果
+---------------------+
| Tables_in_menagerie |
+---------------------+
| pet                 |
+---------------------+
1 row in set (0.00 sec)
```

## おわりに
MySQLの勉強を始めようと思ったものの、最初のテーブル構築までで時間がかかったので、やり方をコマンドを省略せずにまとめました。
MySQLをこれから始める方の参考になれば幸いです。

## 参考
[Docker Hub MySQL original image][link-1]
[MySQL Tutorial][link-2]