MySQLのコンテナを作る方法


- 環境
    - CentOS Linux release 7.8.2003 (Core)
    - Docker Engine 19.03.8
    - docker-compose version 1.25.5

# 1. docker-compose.ymlを作る
```yml
version: '3.8'
services:
  app:
...省略...
  logdb:
    image: mysql:8.0.20
    environment:
      MYSQL_DATABASE: logdb
      MYSQL_USER: log
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
      MYSQL_TCP_PORT: 3306
    ports:
      - 3304:3306
    volumes:
      - ./logdb/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./logdb/init:/docker-entrypoint-initdb.d
    container_name: logdb
    restart: always
```

## `image`にはDockerHubにあるMySQLを指定
指定のやり方はいくつかあるようだが、後でバージョンがわかる書き方にしてみた。
[mysql - Docker Hub](https://hub.docker.com/_/mysql)

## `environment`にデータベースの情報を指定
- `MYSQL_DATABASE` : 初期作成するデータベース名を指定
- `MYSQL_USER``MYSQL_PASSWORD` : `MYSQL_DATABASE`で指定したデータベースのスーパーユーザーになるユーザーとそのパスワードを指定
- `MYSQL_ROOT_PASSWORD` : rootユーザーのパスワードを指定
    - [このパスワード指定は必須で、忘れるとコンテナの作成に失敗する](https://qiita.com/ponsuke0531/items/973b4beecd99ba23ce66)
- `MYSQL_TCP_PORT` : MySQLのポート番号を指定
    - 指定しなくても3306になりそうだけれど自信がないので指定しておく

## `ports`に公開するポートを指定
ほかのコンテナやホストの外部からデータベースを使えるように`{ホストでのポート}:{コンテナでのポート}`を指定

- 参考 : [Docker Compose - docker-compose.yml リファレンス - Qiita](https://qiita.com/zembutsu/items/9e9d80e05e36e882caaa#ports)

## `volumes`の指定
### 設定ファイルの配置
文字コードなどの必要な設定を記載した設定ファイル`my.cnf`を用意しておき`/etc/mysql/conf.d`に配置する

```cnf:./logdb/my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
init-connect='SET NAMES utf8mb4'
skip-character-set-client-handshake
port=3306
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

[mysqldump]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

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

### 初期テーブル作成用SQLの配置
最初に作成しておいてほしいテーブル定義を書いたSQLを`init`ディレクトリに格納しておき`docker-entrypoint-initdb.d`に配置するとデータベース作成後に作成しておいてもらえる
データを作成しておきたい場合もSQLをディレクトリに入れておけば実行してもらえる

```sql:./logdb/init/sql.sql
USE logdb;

DROP TABLE IF EXISTS rhel6;
CREATE TABLE rhel6 (
-- ...省略...
);

DROP TABLE IF EXISTS rhel7;
CREATE TABLE rhel7 (
-- ...省略...
);
```


- 参考 : [Docker MySQLコンテナ起動時に初期データを投入する - Qiita](https://qiita.com/NagaokaKenichi/items/ae037963b33a85df33f5)


## `restart`でコンテナの自動起動を設定
`always`(常に再起動)を設定することでホストを起動したときに自動で起動してもらえる

- 参考 : [Docker Compose restart の挙動 - 技術備忘記](http://junchang1031.hatenablog.com/entry/2016/05/18/000605)

# 2. コンテナを作る
`--no-recreate`をつけて既存のコンテナを作り直さないようにしてコンテナを作成する

- 参考 : [docker-compose up | Docker Documentation](https://matsuand.github.io/docs.docker.jp.onthefly/compose/reference/up/)

```bash
$ docker-compose up -d --no-recreate --build
...省略...
Creating logdb                   ... done

$ docker ps
CONTAINER ID       IMAGE             COMMAND            CREATED             STATUS              PORTS                             NAMES
625ce72a719        mysql:8.0.20      "docker-entry…"   23 seconds ago      Up 21 seconds       33060/tcp, 0.0.0.0:3304->3306/tcp logdb
5cead7ffb9b        host-java...      "/usr/sbin/init"   7 hours ago         Up 28 minutes       0.0.0.0:18080->8080/tcp           app
```

# 3. データベースにログインしてみる

## ホストからログイン
ホストからつなぐときは、[コンテナに入る] > [データベースにログイン]でちょっと面倒くさい
けれどホストからつなぐことはあまりない・・・と思う

```bash
# 1.コンテナに入る
$ docker exec -it logdb bash

# 2. データベースにログイン
root@793f7ed80b16:/# mysql -u log -D logdb -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 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.

# my.cnfの設定が使われてるっぽい
mysql> select default_character_set_name, default_collation_name from information_schema.schemata where schema_name = 'logdb';
+----------------------------+------------------------+
| DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME |
+----------------------------+------------------------+
| utf8mb4                    | utf8mb4_general_ci     |
+----------------------------+------------------------+
1 row in set (0.00 sec)

# テーブルもできている
mysql> show tables;
+-----------------+
| Tables_in_logdb |
+-----------------+
| rhel6           |
| rhel7           |
+-----------------+
2 rows in set (0.00 sec)

mysql>
```
## アプリ用コンテナからログイン
ほかのコンテナからログインするときは`-h`(ホスト)に「コンテナ名」を指定する

- 参考 : [他のDockerコンテナからコンテナ内のMySQLに接続する - Qiita](https://qiita.com/YuitoSato/items/4a4b46f5670b45739a37)

```bash
$ mysql -h logdb -u log -D logdb -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.20 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>

```

## ローカルPC(Windows)のGitBashでログイン
ホスト外部からログインするときは`-h`(ホスト)に「ホストのIPアドレス」を`-P`(ポート)に「docker-compose.ymlで指定したホストのポート」を指定する
`winpty`はGitBashを使用しているからつけているだけなので普通はいらない

- 参考 : [MySQLの覚書 | MySQLのコマンド](http://amaraimusi.sakura.ne.jp/note_prg/mysql/cmd_note.html)

```bash
$ winpty mysql -h {ホストのパブリックIP} -P 3304 -u log -D logdb -p
Enter password: *******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.20 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>
```