Dockerで永続化したmySQLの環境を作る！

# はじめに
この記事は`Docker`を使って`mySQL`の環境構築までを記します。
初心者のため間違い等ございましたらご指摘いただけると幸いです。

# 前提条件
* 基本的なSQLが書けること。
* `Docker`をインストールしていて、基本的な操作方法がわかること。

`Docker`をインストールしていない場合は以下のリンクを参考にインストールしてみてください。
[たぶん動くから！Docker始めてみよう！](https://qiita.com/leafeon00000/items/a2d694ac52b542c76e01)

#環境
`macOS Catalina` : 10.15.7
`Visual Studio Code` : 1.42.1

```sh:ターミナル
$ docker --version
Docker version 19.03.13
```

#フォルダ構成
フォルダ構成は以下の通りに作成しました。

```:フォルダ構成
.
├── docker-compose.yml
└── mysql
    ├── Dockerfile
    ├── db　←最初は空（フォルダのみ作成）
    │   └──（永続化のためのファイル等省略）
    ├── initdb.d
    │   └── init.sql
    └── my.cnf
```

##各ファイルについて
各ファイルは以下の様に作成しました。
###Dockerfile
```docker:./mysql/Dockerfile
#使うDockerイメージ
FROM mysql

#ポートの設定
EXPOSE 3306

#MySQL設定ファイルをコピー
COPY ./my.cnf /etc/mysql/conf.d/my.cnf

#docker run時の実行コマンド
CMD ["mysqld"]
```


###docker-compose.yml

```docker:./docker-compose.yml
version: "3"
services:
  mysql:
    build: ./mysql/
    volumes:
      - ./mysql/initdb.d:/docker-entrypoint-initdb.d #初期処理のフォルダ。初回起動のみでおｋ
      - ./mysql/db:/var/lib/mysql #ここにデータ永続化するためのファイルが入る。
    image: mysqlapp
    container_name: "mysqlapp"
    environment:
      - MYSQL_ROOT_PASSWORD=pass
```
* `volumes`の`- ./mysql/initdb.d:/docker-entrypoint-initdb.d`(上段)は初期処理です。一度コンテナを起動させた後は削除しても問題ありません。
* `volumes`の`- ./mysql/db:/var/lib/mysql`(下段)は永続化のための処理です。このデータベースやテーブルを編集した場合このフォルダに自動的にマウントされ永続化してくれます。

###init.sql
初期処理で動かすSQLです。

```sql:./mysql/initdb.d/init.sql
DROP DATABASE IF EXISTS testdb;
CREATE DATABASE testdb;
USE testdb;
DROP TABLE IF EXISTS test;

CREATE TABLE test
(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name TEXT NOT NULL
)DEFAULT CHARACTER
  SET=utf8;

  INSERT INTO test
    (name)
  VALUES
    ("田中"),
    ("鈴木"),
    ("ああああああ");
```


###my.cnf
mysqklの設定ファイルです。

```config:./mysql/my.cnf
[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8
```

#コンテナの起動
`docker-compose.yml`を配置したディレクトリに移動し、以下のコードで起動します。

```sh:ターミナル
$ docker-compose up -d
Creating network "mysql_default" with the default driver
Creating mysqlapp ... done

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
d97ade0a7ede        mysqlapp            "docker-entrypoint.s…"   35 seconds ago      Up 29 seconds       3306/tcp, 33060/tcp   mysqlapp
```
`docker ps`コマンドで起動中のコンテナを確認できます。
`docker-compose.yml`の`container_name`を記述していた場合、`NAMES`の項目をメモします。記述していない場合は`CONTAINER ID`をメモしてください。

#mySQLコンテナ
起動中のmySQLコンテナ内に入ります。

```sh:ターミナル
$ docker exec -it mysqlapp /bin/bash 
root@d97ade0a7ede:/# 
```

`mysqlapp`は前の章の`docker ps`コマンドでメモした内容を入力してください。

##mySQLの操作

データベースを確認します。

```sql:ターミナル
root@d97ade0a7ede:/# mysql -uroot -ppass
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.22 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| testdb             |
+--------------------+
5 rows in set (0.02 sec) 
```

`testdb`のデータベースが作成されていますね！
続いてテーブルを確認しましょう。

```sql:ターミナル
mysql> use testdb
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| test             |
+------------------+
1 row in set (0.00 sec)

mysql> select * from test;
+----+--------------------+
| id | name               |
+----+--------------------+
|  1 | 田中               |
|  2 | 鈴木               |
|  3 | ああああああ       |
+----+--------------------+
3 rows in set (0.01 sec)
```
きちんとテーブルまで作成されていますね！

##テーブルの更新
テーブルを更新し、データが永続化されているか確認します。

```sql:ターミナル
mysql> INSERT INTO test (name) VALUES ("test");
Query OK, 1 row affected (0.02 sec)

mysql> select * from test;
+----+--------------------+
| id | name               |
+----+--------------------+
|  1 | 田中               |
|  2 | 鈴木               |
|  3 | ああああああ       |
|  4 | test               |
+----+--------------------+
4 rows in set (0.00 sec)
```
テーブルが更新されましたね！

##永続化の確認
データが永続化されているか確認するため、一度コンテナを落とし、再度起動して確認します。

```sh:ターミナル
$ docker-compose down
Stopping mysqlapp ... done
Removing mysqlapp ... done
Removing network mysql_default
```

起動し直して確認します。

```sql:ターミナル
(略)
mysql> select * from test
    -> ;
+----+--------------------+
| id | name               |
+----+--------------------+
|  1 | 田中               |
|  2 | 鈴木               |
|  3 | ああああああ       |
|  4 | test               |
+----+--------------------+
4 rows in set (0.01 sec)
```

きちんと`test`と入力した物が残っていて永続化できていますね！

#終わりに
mySQLを使ったコンテナ作成の一助になれば光栄です。
docker-composeを使った構築は複数のコンテナを同時に起動するために有用ですが今回はmySQLのみとなってしまいました。
次回はDBと他のコンテナを連携した記事を書きたいなー…~~（毎回同じ様なことを言っている気がする）~~