dockerを初めて触ってみる(DBコンテナを立ててみよう)

#やること
dockerでMySQLコンテナを立ててみて、dockerを体験する

開発環境は以下の通り

- OS: macOS High Sierra
- docker: 17.12.0-ce


#こんな方向け

- dockerに興味はあるけどよくわからない
- とりあえず触って見たい
- コンテナの立て方を覚えたい

#dockerとは？
一言で言うとコンテナ型のアプリケーション実行環境。
dockerの基本的な流れは以下

1. イメージの作成(DockerFileの作成) or ダウンロード(`docker pull`)
1. コンテナの実行(`docker run`)

1で作ったイメージを元に同一の実行環境(コンテナ)が作れる。
イメージはDockerFileというスクリプトを元に作成することができる。
イメージは公式からも配布されており、簡単にMySQL,Python,phpなどの様々な実行環境を容易に実現することができる。
本記事ではDockerFileの記述を行わず、公式からMySQLのイメージを落としてコンテナを実行することを目的とする。

#インストール
公式からインストーラをダウンロード [docker docs install Docker](https://docs.docker.com/install/#updates-and-patches)

macは[ここ](https://download.docker.com/mac/stable/Docker.dmg)
windowsは[ここ](https://download.docker.com/win/stable/Docker%20for%20Windows%20Installer.exe)

#イメージのダウンロード
dockerのイメージファイルはdockerHubに上がっている。[dockerHub](https://hub.docker.com/)
ここでほしいイメージファイルを検索すれば良い。
もしくは、`docker search`でも探すことができる。
mysqlのイメージを探してみると

```bash
$ docker search mysql
NAME                                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mysql                                                  MySQL is a widely used, open-source relation…   5757                [OK]                
mariadb                                                MariaDB is a community-developed fork of MyS…   1824                [OK]                
mysql/mysql-server                                     Optimized MySQL Server Docker images. Create…   397                                     [OK]
zabbix/zabbix-server-mysql                             Zabbix Server with MySQL database support       90                                      [OK]
hypriot/rpi-mysql                                      RPi-compatible Docker Image with Mysql          79                                      
centurylink/mysql                                      Image containing mysql. Optimized to be link…   59                                      [OK]
zabbix/zabbix-web-nginx-mysql                          Zabbix frontend based on Nginx web-server wi…   46                                      [OK]
tutum/mysql                                            Base docker image to run a 
```

というようにたくさん出てくるがofficialの`mysql`が良さげなのでこれをダウンロードする。
ダウンロードは`docker pull`で行う

```bash
$ docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
2a72cbf407d6: Pull complete 
38680a9b47a8: Pull complete 
4c732aa0eb1b: Pull complete 
c5317a34eddd: Pull complete 
f92be680366c: Pull complete 
e8ecd8bec5ab: Pull complete 
2a650284a6a8: Pull complete 
5b5108d08c6d: Pull complete 
beaff1261757: Pull complete 
c1a55c6375b5: Pull complete 
8181cde51c65: Pull complete 
Digest: sha256:691c55aabb3c4e3b89b953dd2f022f7ea845e5443954767d321d5f5fa394e28c
Status: Downloaded newer image for mysql:latest
```

#動かしてみる
mysqlコンテナをしっかり動かすには様々なオプションが必要だがここでは、失敗しながら順を追って説明する。

##とりあえず実行 `docker run （イメージ名）`
コンテナの実行は`docker run`で行う。

```bash
$ docker run mysql
error: database is uninitialized and password option is not specified 
  You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD
```
怒られる。環境変数のMYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD, MYSQL_RANDOM_ROOT_PASSWORDのいずれかを設定しろと言うことだ。
環境変数の設定は`オプション-e`で行う。

```bash
$ docker run -e MYSQL_ROOT_PASSWORD=root mysql
Initializing database
2018-03-15T03:43:02.944040Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2018-03-15T03:43:03.582239Z 0 [Warning] InnoDB: New log files created, LSN=45790
2018-03-15T03:43:03.662870Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2018-03-15T03:43:03.723287Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: f73419d2-2802-11e8-b24d-0242ac110002.
(略)
2018-03-15T03:43:13.320423Z 0 [Warning] 'proxies_priv' entry '@ root@localhost' ignored in --skip-name-resolve mode.
2018-03-15T03:43:13.323137Z 0 [Warning] 'tables_priv' entry 'user mysql.session@localhost' ignored in --skip-name-resolve mode.
2018-03-15T03:43:13.323270Z 0 [Warning] 'tables_priv' entry 'sys_config mysql.sys@localhost' ignored in --skip-name-resolve mode.
2018-03-15T03:43:13.329318Z 0 [Note] Event Scheduler: Loaded 0 events
2018-03-15T03:43:13.330280Z 0 [Note] mysqld: ready for connections.
Version: '5.7.21'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server (GPL)
```
とりあえずこれで動いたが、これではmysqlの操作ができない

##コンテナに入ってみる `docker exec -it (コンテナ名 or id) bin/bash`
とりあえず動いてるコンテナを確認する。
コンテナ一覧は`docker container ls`でみることができる

```bash
$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
9f3ff629ea95        mysql               "docker-entrypoint.s…"   6 minutes ago       Up 6 minutes        3306/tcp            friendly_euclid
```
コンテナに入るには`docker exec`を使う。これは指定したコンテナに指定したコマンドを実行させるもので、実行するコマンドに`bin/bash`をしているすることでコンテナに入ることができる。
さらにオプションに`-i`を入れることで入力、`-t`を入れることで出力をコンテナと共有することができる。(つけないとうんともすんともいわない)
とりあえずは`docker exec -it (コンテナ名 or id) bin/bash`で覚えよう。（idははじめの4文字のみで良い）

```bash
$ docker exec -it 9f3f bin/bash
root@9f3ff629ea95:/# 
```
入れたmysqlを実行してみる

```bash
root@9f3ff629ea95:/# mysql mysql -uroot -p
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, 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>  exit
Bye
root@9f3ff629ea95:/# exit
exit
```

動いた！パスワードは`docker run`時に`MYSQL_ROOT_PASSWORD`で設定した値。
コンテナからは`exit`で抜けられる。
最後に`docker container stop`でコンテナを停止し、`docker container rm`でコンテナを削除する

```bash
$ docker container stop 9f3f
9f3f
$ docker container rm  9f3f
9f3f
$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```
##外部から接続してみる `docker run -p （ホストのポート）:(コンテナのポート)`
このままではコンテナ内に外部からアクセスできずあまり意味がない。
そのため外部からもアクセスできるようにするためにポートフォワーディングする。
ポートフォワーディングはオプション`-p （ホストのポート）:(コンテナのポート)`でできる。
また、先ほどはコンテナ名を設定しなかったがオプション`--name`で設定できる。

```bash
$ docker run --name db -e MYSQL_ROOT_PASSWORD=root -p 33306:3306  mysql
Initializing database
2018-03-15T04:07:38.605934Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2018-03-15T04:07:39.107155Z 0 [Warning] InnoDB: New log files created, LSN=45790
2018-03-15T04:07:39.194810Z 0 [Warning] InnoDB: Creating foreign key constraint system tables.
2018-03-15T04:07:39.204067Z 0 [Warning] No existing UUID has been found, so we assume that this is the first time that this server has been started. Generating a new UUID: 66a89a59-2806-11e8-a4eb-0242ac110002.
(略)
```
接続してみる

```bash
$ mysql -h 127.0.0.1 -P 33306 -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.21 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, 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> 
```

接続できた！接続するときにホストをIPで指定する必要があることに注意すること

#おわり
これで使い切りのDBコンテナをすることができた。
コンテナは使い切りの為消したらデータが失われてしまうので永続化する必要がある [(参考)](https://qiita.com/onokatio/items/fcc9f8f94f8533bb030a)

こんな感じでコマンド一つで簡単にDBなどが作れる為、ためしにDBは欲しいがローカルのものを汚したくない時などに便利だ。他にも自分でイメージファイルを作れば本番環境への以降も簡単にできる。
コマンドも多いが覚えにくわけでもなく、公式のリファレンスも充実している。
Qiitaには[コマンドチートシートの記事](https://qiita.com/wMETAw/items/34ba5c980e2a38e548db)もあるため参考にすると良い。