docker-composeでMySQL5.7を起動して接続してみた

この記事は、楽にDockerコンテナでMySQLを起動してみたいDocker初心者に向けて書いています。
また、SpringBoot(FrameWork)での開発をベースにしているため、対象者が限定的になってしまうかもしれないのでご注意ください。
![vertical.png](https://qiita-image-store.s3.amazonaws.com/0/272691/34aea8e5-d131-9719-1f75-a7492f38ac6f.png)
## 前提

- Dockerとは何か?ざっくりと概要を知っていること
- Docker for Mac をインストール済みであること

※Dockerをまだインストールしていない方は、下記リンクを参考にDockerを起動するところまでやりましょう
Qiita：https://qiita.com/scrummasudar/items/750aa52f4e0e747eed68

開発環境は以下の通りです。
### 開発環境
- Mac OS High Sierra
- IntelliJ IDEA
- SpringBoot 2.0.5
- Java8
- Docker

## そもそもDockerとは??
簡潔に述べると、　オープンソースのコンテナ管理ソフトウェアのことです。
Dockerコンテナを使うことで、アプリケーションビルド、デプロイを高速化できるとのことです。詳しい説明はスキップしますので以下をご参考にしてください。
Qiita：https://qiita.com/gold-kou/items/44860fbda1a34a001fc1
公式ドキュメント：https://docs.docker.com/

### Docker Composeとは？？

多様なコンテナ（docker）を定義して、起動することができるツールのこと。基本的にYAMLファイルでサービスの環境設定を行うことができます。また、一つのコマンドだけで簡単に始められるとのこと。
※DockerForMacをインストールすると自動的に付属してくるので、別途インストール不要

## 今回やること
-  docker-composeコマンドを使って、MySQL5.7（公式イメージ）を起動してみる
-  起動したMySQL5.7に接続してみる
-  準備した設定ファイル通りにDBやテーブルが初期化されているか確認する
-  出力したクエリログをみてみる

## 手順

#### 1. Dockerがインストールされているか確認する

```:Terminal
$ docker --version
Docker version 18.03, build c97c6d6 #インストールされていればバージョンが表示される

$ docker-compose --version
docker-compose version 1.22.0, build 8dd22a9

$ docker-machine --version
docker-machine version 0.14.0, build 9ba6da9
```

#### 2. Dockerfileを作成する
 ディレクトリ構成は以下のようになります。

```:構成
sample-project/
             ├ docker/
             |       └ mysql/
             |              ├ conf.d/
             |              |       └ my.cnf
             |              ├ initdb.d/
             |              |         ├ schema.sql
             |              |         └ testdata.sql
             |              └ Dockerfile
             └ docker-compose.yml                      
```
**Dockerfile**は、どのようなimageをビルドするかを注文する指示書のようなものです。
MySQLのversion5.7を使用するため、公式イメージをビルドするように以下のように記述します。

```dockerfile:Dockerfile
FROM mysql:5.7
RUN touch /var/log/mysql/mysqld.log # 指定の場所にログを記録するファイルを作る
```

#### 3. docker-compose.ymlを作成する
このYAMLファイルでは、複数のサービスの設定が可能です。具体的には各々のサービスのポート番号を指定したり、記憶領域（volume）の設定をすることができます。

```yml:docker-compose.yml
version: '3.3'                 # docker-composeのversionを指定
services:
  db:
    build: ./docker/mysql       # Dockerfileの置き場所を指定
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: sample_db
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: rootpassword
    ports:
      - "3314:3306"
    volumes:
      - ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d
      - ./docker/mysql/conf.d:/etc/mysql/conf.d
      - ./log/mysql:/var/log/mysql

```
#### 4. my.cnfを作成する

ここでは、MySQLの設定をすることができます。

```conf:my.cnf
[mysqld]
character-set-server=utf8mb4       # mysqlサーバー側が使用する文字コード
explicit-defaults-for-timestamp=1　  # テーブルにTimeStamp型のカラムをもつ場合、推奨
general-log=1　                  # 実行したクエリの全ての履歴が記録される（defaultではOFFになっているらしい）
general-log-file=/var/log/mysql/mysqld.log # ログの出力先

[client]
default-character-set=utf8mb4　　　　　　　　　　　　　　　# mysqlのクライアント側が使用する文字コード
```
#### 5. テーブル定義ファイルを作成する
テーブルの作成を初期化処理として行いたいので、DDLファイルを用意します。

```sql:schema.sql
CREATE TABLE users (
    id INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(32) NOT NULL,
    email VARCHAR(32) NOT NULL,
    PRIMARY KEY (id)
);
```

#### 6. テストデータを作成する
あらかじめテーブルにデータを準備することができます。

```sql:testdata.sql
INSERT INTO users (id,name,email) VALUES (1, 'TOM','xxxx@mail.co.jp');
```
#### 7. docker-composeコマンドを実行する
以下コマンドはプロジェクトのルートディレクトリで実行します。

```terminal:Terminal
$ docker-compose up -d # コンテナを作成しスタートする
Creating network "sample-project_default" with the default driver
Creating sample-project_db_1 ... done

$ docker-compose ps # 存在するコンテナのリストを表示する
        Name                   Command           State           Ports         
--------------------------------------------------------------------------------
sample-project_db_1    docker-entrypoint.sh     Up      0.0.0.0:3314->3306/tcp
                       mysqld                           , 33060/tcp  

↓その他コマンド↓
$ docker-compose stop # サービスを停止させる
$ docker-compose down # コンテナの停止、削除、さらにネットワーク、記憶領域を全て削除
```
#### 8. 起動したMySQLに接続してみる
では、早速docker-composeで立ち上げたMysqlに接続してみます。

```terminal:Terminal
$ docker exec -it sample-project_db_1 bash # sample-project_db_1というコンテナに入りコマンドを実行
# mysql -u user -p # ログインする
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
mysql>　use sample_db;
Database changed

Database changed
mysql> show tables; # テーブルが作られているか確認する
+---------------------+
| Tables_in_sample_db |
+---------------------+
| users               |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from users; # 仕込んだデータが入っているか確認する
+----+------+-----------------+
| id | name | email           |
+----+------+-----------------+
|  1 | TOM  | xxxx@mail.co.jp |
+----+------+-----------------+
1 row in set (0.00 sec)

```

このままだとコンテナ内からMysqlに接続しているだけなので、接続方法を換えて確認します。
ホスト名、ポートを指定してログインします。（指定しない場合デフォルトのポート3306に繋ぐようです）

```:Terminal
$ mysql --host 127.0.0.1 --port 3314 -u user -p 
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g
・
・
mysql>
```

#### 9. ログを確認する

先ほど設定した場所にファイルができていることを確認します。

```:ディレクトリ構成
sample-project/
              ├ docker
              ├ log/
              |    └ mysql/
              ├ src       └ mysqld.log
              |
              └ docker-compose.yml
```
ファイルの中身はこんな感じになりました。

```mysqld.log

mysqld, Version: 5.7.23-log (MySQL Community Server (GPL)). started with:
Tcp port: 0  Unix socket: /var/run/mysqld/mysqld.sock
Time                 Id Command    Argument
2018-10-13T11:38:04.918533Z	    1 Query	CREATE DATABASE mysql;
2018-10-13T11:38:04.919437Z	    1 Query	USE mysql;
　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　　　　　　・
　　　　　　　　　　　　以下割愛
```
今回、全てのクエリログを出す設定にしているため、ファイルのサイズはなかなか大きいようです（6.71MB）

## 感想

コンテナの概念への理解度がまだまだ低いのでなんとなくやってる感がありますが、ローカルでMySQLをインストールして諸々いじくるよりも楽で、ローカル環境を汚さないので、これからどんどん使っていこうと思いました。
今回紹介していませんが、Springbootで開発したアプリケーションから接続する手順も今後シェアできたらいいなと思います。

### その他の参考ページ

- 外部リンク1：http://dqn.sakusakutto.jp/2015/10/docker_mysqld_tutorial.html 
- 外部リンク2：https://blog.local-c.com/archives/1984