Ubuntu に Docker(+ Docker-Compose) + MySQL を入れる

# Ubuntu に Docker + MySQL を入れてみる
Ubuntu の環境は既に作成済なのが前提
express と接続して中身見れるようにするのは次回

- PC環境
  - Vagrant 2.2.7
     - VirtualBox 6.1.2
         - Ubuntu 18.04 
             - ここに Docker-CE + MySQL を入れていく
             - 便利なので Docker-Compose も使うよ

## Docker をインストールする
[参考サイト](https://qiita.com/shubatto/items/105f5b90e1cd91ba7c4c)を見ながらやれば、特に引っ掛からないはず。
### Docker インストール前準備
```bash
# apt更新
$ sudo apt-get update

# aptがHTTPS経由でリポジトリを使用できるようにする
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

# Docker公式GPGキー追加
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# キーを確認
$ sudo apt-key fingerprint 0EBFCD88

# stable設定
$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```

### Docker インストール
```bash
# apt更新
$ sudo apt-get update

# 最新バージョンをインストール
$ sudo apt-get install docker-ce
```

### Docker インストール後の話
```bash
# docker グループを作成する
$ sudo groupadd docker

# ユーザを docker グループに追加する
$ sudo usermod -aG docker $USER

# 再起動してグループメンバーシップを認識させる
$ sudo reboot
```

```bash
# sudo なしで docker が動くのを確認
$ docker run hello-world
```

↓こんなのが出ます。タイミングとかで Digest が変わったりとかはするかも。

```
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:9572f7cdcee8591948c2963463447a53466950b3fc15a247fcad1917ca215a2f
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```

### Docker-Compose をインストールする
出来るだけ最新の方がいいかも。
最新は、[Docker compose release page](https://github.com/docker/compose/releases)にある。
今は、 1.25.4 が最新？

```bash
# 最新をダウンロード
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 実行権限を付与
$ sudo chmod +x /usr/local/bin/docker-compose

# インストール確認
$ docker-compose --version
```

インストール確認すると↓のような出力が出る。

```bash
docker-compose version 1.25.4, build 8d51620a
```

## MySQL をインストールする
他のサイトを色々確認したんだけど、何か分かりづらいので手元に纏める。

express + MySQL の場合は、[ココ](https://qiita.com/tiwu_official/items/9ffc8e1fd1173b1a9e40)を参考にしたらいいと思う。
最終的にやりたいのは、以下の２つのサーバー？を用意して、
ExpressからMySQLのデータ参照して使いたい。

- Node.js + Express (+ MySQL Client) のインストールされている Ubuntu 18.04 サーバー？
- Docker-CE(+ Docker-Compose) + MySQL + Redis のインストールされている Ubuntu 18.04 サーバー？ ★今やってるのはコレ★

Expressの方にMySQLをインストールしないと使えないの、結構気づかなかったよね……。ゲフンゲフン。
~~途中で「もう同じサーバーでいいじゃん」ってあきらめそうになった。~~

### Docker-CE(+ Docker-Compose)上に、MySQLをインストールする
とりあえずMySQL使える環境を作る。ファイルの構成とかは、[ココ](https://qiita.com/A-Kira/items/f401aea261693c395966)のを参考にしています。

なので構成はそのままこうなる。

```
MySQLTest/
├── docker/
│   └── db/
│       ├── data/
│       ├── my.cnf
│       └── sql/
│           ├── 001-create-tables.sql
│           └── init-database.sh
├── docker-compose.yml
└── init-mysql.sh
```

globalにしたくないので、フォルダ作成から。

```bash
mkdir MySQLTest
cd MySQLTest
```
MySQLをインストールする

```bash
npm install mysql --save
```

後で作る docker-compose.yml で、存在しなかったフォルダは自動的に作ってくれるんだけど、
my.cnf はファイルとして作りたいので、そこまでのフォルダは作っておく。

```bash
mkdir docker
cd docker
mkdir db
cd db
```

nano(テキストエディタ)を開いて、 my.cnf を作る。

```bash
sudo nano my.cnf
```

my.cnf の中身はコレ。文字コードの設定です。ファイル作成して保存しておく。

```text:my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

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

次に docker-compose.yml を作ります。MySQLTestフォルダに戻ってから、
nano(テキストエディタ)で docker-compose.yml を作成します。

```bash
cd ../../ #dbフォルダに居たらMySQLTestに戻る、そうじゃなければ無視して
sudo nano docker-compose.yml
```

docker-compose.yml の中身はコレ。

```docker-compose.yml
version: '3'

services:
  # MySQL
  db:
    image: mysql
    container_name: mysql_host
    environment:
        MYSQL_ROOT_PASSWORD: root
        MYSQL_DATABASE: test_database
        MYSQL_USER: docker
        MYSQL_PASSWORD: docker
        TZ: 'Asia/Tokyo'
    command: "mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci"
    volumes:
        - ./docker/db/data:/var/lib/mysql
        - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
        - ./docker/db/sql:/docker-entrypoint-initdb.d
    ports:
        - 3306:3306
```

これを保存したら、次はmysql初期化用のシェルを作ります。
docker-compose.yml と同じ場所で init-mysql.sh を作ります。
中身はコレ。

```init-mysql.sh
#!/bin/sh
docker-compose exec db bash -c "chmod 0775 docker-entrypoint-initdb.d/init-database.sh"
docker-compose exec db bash -c "./docker-entrypoint-initdb.d/init-database.sh"
```

### Dockerを起動＆停止

```bash
docker-compose up -d
```

フォルダとか生成されるので、Docker起動されたのを確認

```bash
docker-compose ps
```

↑のコマンドを実行すると、こんなのが出力される。一覧が出るみたい。

```
   Name                 Command               State                 Ports
---------------------------------------------------------------------------------------
mysql_host   docker-entrypoint.sh mysql ...   Up      0.0.0.0:3306->3306/tcp, 33060/tcp
```

他にも書いたり用意するのがあるので、一旦終了させる。
docker-compose.yml に書いてあれば、纏めてやってくれるから便利。

```bash
docker-compose down
```

### 残りのファイルを作る
さっき作らなかった、 001-create-tables.sql と init-database.sh を作ります。

```
MySQLTest/
├── docker/
│   └── db/
│       ├── data/
│       ├── my.cnf
│       └── sql/　　↓この２つ
│           ├── 001-create-tables.sql
│           └── init-database.sh
├── docker-compose.yml
└── init-mysql.sh
```

#### 001-create-tables.sql を作る
sqlフォルダ内でテキストエディタを開く。

```sql:001-create-tables.sql
---- drop ----
DROP TABLE IF EXISTS `test_table`;

---- create ----
create table IF not exists `test_table`
(
 `id`               INT(20) AUTO_INCREMENT,
 `name`             VARCHAR(20) NOT NULL,
 `created_at`       Datetime DEFAULT NULL,
 `updated_at`       Datetime DEFAULT NULL,
    PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
```

これを 001-create-tables.sql として保存する。

#### init-database.sh を作る
sqlフォルダ内でテキストエディタを開く。

```bash:init-database.sh
#!/usr/bin/env bash
#wait for the MySQL Server to come up
#sleep 90s

#run the setup script to create the DB and the schema in the DB
mysql -u docker -pdocker test_database < "/docker-entrypoint-initdb.d/001-create-tables.sql"
```

これを init-database.sh として保存する。
実行権限は、init-mysql.sh で chmod してるから気にしなくていい。

## MySQL起動＆データ入力と表示
ようやく準備が出来たので、init-mysql.sh を実行。

```
MySQLTest/
├── docker/
│   └── db/
│       ├── data/
│       ├── my.cnf
│       └── sql/
│           ├── 001-create-tables.sql
│           └── init-database.sh
├── docker-compose.yml
└── init-mysql.sh ←コレ
```

### DB初期化(シェル実行)
```
./init-mysql.sh
```

これでデータベースは出来た（テーブルは空っぽ）ので、確認する

#### MySQLに接続

mysql_host は、 docker-compose.yml の container_name と同じのにする。

```bash
$ docker exec -it mysql_host bash
```

接続できると、以下みたいな出力になる。
(root@の後ろはコンテナIDなので同じにはならないはず)

```
root@ff7eb30d5b23:/#
```

MySQLにログインして、データベースが出来てるか確認しよう
ユーザー名とパスワード入力

```
mysql -uroot -p
```

#### 使うデータベースを指定する
use test_database; を実行する。
↓こんな感じ

```
mysql> use test_database;
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>
```

#### テーブルを表示する
データがあれば↓みたいになるが、
無ければ 0 row in set (0.00 sec) と言われる。

```
mysql> SELECT * FROM test_table;
+----+------+---------------------+---------------------+
| id | name | created_at          | updated_at          |
+----+------+---------------------+---------------------+
|  1 | TOM  | 2020-02-06 00:00:00 | 2020-02-06 00:00:00 |
+----+------+---------------------+---------------------+
1 row in set (0.00 sec)

mysql>
```

テーブル自体が無かったらこうなる。

```
mysql> SELECT * FROM table;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'table' at line 1
mysql>
```
#### テーブルにデータを入力する
とりあえずSQL文で入力する

```
INSERT INTO test_table (id,name,created_at,updated_at) VALUES (1, 'TOM','2020-02-06', '2020-02-06');
```

ちゃんと入力出来てたらこうなる

```
mysql> INSERT INTO test_table (id,name,created_at,updated_at) VALUES (1, 'TOM', '2020-02-06', '2020-02-06');
Query OK, 1 row affected (0.04 sec)

mysql>
```

もう一度テーブルを表示してみると、↓こうなる

```
mysql> SELECT * FROM test_table;
+----+------+---------------------+---------------------+
| id | name | created_at          | updated_at          |
+----+------+---------------------+---------------------+
|  1 | TOM  | 2020-02-06 00:00:00 | 2020-02-06 00:00:00 |
+----+------+---------------------+---------------------+
1 row in set (0.00 sec)

mysql>
```

これでサンプルデータ作るところまで、完了。
exit コマンドで抜けておく。

# 参考
- Dockerの話
  - https://qiita.com/shubatto/items/105f5b90e1cd91ba7c4c/
- Docker公式の話
  - https://docs.docker.com/install/linux/docker-ce/ubuntu/
- Node.jsとExpressとMySQLの簡単サンプル
  - https://qiita.com/tiwu_official/items/9ffc8e1fd1173b1a9e40
- docker-compose でMySQL環境簡単構築
  - https://qiita.com/A-Kira/items/f401aea261693c395966
- Docker compose release page
  - https://github.com/docker/compose/releases/
- 初心者向けdocker-composeコマンド逆引き
  - https://qiita.com/okyk/items/a374ddb3f853d1688820
- docker-composeでMySQL5.7を起動して接続してみた
  - https://qiita.com/MJ-Hippos/items/58d0f98a15656ed65136
- MySQLの話
  - https://qiita.com/astrsk_hori/items/e3d6c237d68be1a6f548
- MySQL, Redisを利用する開発環境を Docker CE で構築する
  - https://qiita.com/rubytomato@github/items/79792a6e4bf205dd4bee