Docker Compose 入門

# 背景
過去に大好評だったDocker入門の内容を2016年版にupdateした再入門投稿3本が終わったので、
まだ紹介していない機能を投稿していきます。

- [Docker Machine 入門(Hyper-Vの場合)](http://qiita.com/ohhara_shiojiri/items/801a24a2c94ff93be82d)
- [Docker Machine 入門(AWSの場合)](http://qiita.com/ohhara_shiojiri/items/9fbb32ecdb999e2df523)
- [Docker 再入門3 2016](http://qiita.com/ohhara_shiojiri/items/cabc644f8a4d1aaf2e36)
- [Docker 再入門2 2016](http://qiita.com/ohhara_shiojiri/items/31a76913cbfdd9d2fe13)
- [Docker 再入門1 2016](http://qiita.com/ohhara_shiojiri/items/98573b074185381d46c8)
- [Docker 入門](http://www.slideshare.net/ShinichiroOhhara/docker-39456836) (SlideShare)

# 動作環境
- ThinkPad X200s OS:Linux MINT 18
- ThinkPad X1 Carbon OS:Windows 10 Pro (Hyper-V)

個人的に開発環境OSはLinuxが主なので、MacOSやWindowsについては優先度が低いのでご了承ください。

## Dockerコンテナの作成方法
これまでの投稿で２種類の作成方法を紹介して来ました。
１つはDockerfileにてOSイメージにパッケージをインストールする方法。
もう１つはDocker Hubから構成済みの公式イメージを使用する方法です。
どちらを使うかは開発環境によって異なりますが、特定環境に依存する事を避ける為にも自作のオレオレイメージよりは公式イメージを積極的に使って行きましょう。

## Dockerコンテナのリンク連携
Dockerコンテナでサービスを構成する場合、基本的に１つのサービスにつき１つのDockerコンテナになります。
これまでの例ではwebサーバーのnginxだけでしたが、通常はバックエンドにデーターベースや他のサービスと連携してサービス全体が構築されます。
Dockerコンテナは各Dockerコンテナ間をリンクして連携する事でこれを実現しています。

## Docker Compose
そうすると当然複数のDockerコンテナを個別に操作する必要が出てきます。つまり各Dockerコンテナを個別に作成してDockerコンテナ間のリンク連携を定義して、各Dockerコンテナサービスを起動します。
また、停止や削除する場合も各Dockerコンテナ毎に指示を出す事になります。
これは面倒くさい！
という訳でこの一連の作業を纏めて行うのが、Docker Composeになります。
主に開発環境の構築やテスト環境などに使われます。

## インストール
Docker for Windows の場合にはDocker Engineと共に一緒にインストールされています。
ここではLinux環境で単体インストールする場合を紹介します。

[Docker Compose](https://github.com/docker/compose)(github)

```
$ sudo -i
# curl -L "https://github.com/docker/compose/releases/download/1.8.1/docker-compose-$(uname -s)-$(uname -m)" > /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   600    0   600    0     0    483      0 --:--:--  0:00:01 --:--:--   483
100 7798k  100 7798k    0     0  1040k      0  0:00:07  0:00:07 --:--:-- 1770k
# chmod +x /usr/local/bin/docker-compose
# exit
$ docker-compose --version
docker-compose version 1.8.1, build 878cff1
```

バージョン表示させて動作確認します。

## 保存場所
サービス全体をプロジェクトとして作成する場合に、今回もDockerfileの時と同様にLinuxやWindowsとOSが異なっても利用出来るオンラインストレージDropboxを保存場所としてここでは使用してみます。ソースファイルが一元管理出来るので、複数の環境で開発している場合にとても便利に利用出来ます。
Dropbox自体のインストールは済ませた状態を前提とします。

## WordPressをDockerで構築
例題はオープンソースCMSとして日本でも大人気のWordPressをDockerコンテナで構築してみましょう。

[Quickstart: Compose and WordPress](https://docs.docker.com/compose/wordpress/)(docker.com)

### プロジェクトファイルの作成
まずはプロジェクト用のディレクトリをDropboxに作成してカレントディレクトリに移動します。

```
$ mkdir Dropbox/docker/my_wordpress
$ cd Dropbox/docker/my_wordpress
```

以下のプロジェクトYAMLファイル(docker-compose.yml)をカレントディレクトリに作成します。

```yaml:docker-compose.yml
version: '2'

services:
   db:
     image: mysql:5.7
     volumes:
       - "./.data/db:/var/lib/mysql"
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: wordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     links:
       - db
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_PASSWORD: wordpress
```

WordPressにはフロントエンドにwebサーバー、バックエンドにデーターベースサーバーの２つのサービスが必要です。
このプロジェクトファイルには、2つのDockerコンテナの作成とリンク連携及びオプションが設定されています。

### プロジェクトの構築
それでは早速、このWordPressプロジェクトをDocker Composeでビルドして実行します。
この時カレントディレクトリのプロジェクトファイルが規定値で読み込まれて関連ファイルも作成されますので、必ずプロジェクト用のディレクトリに移動しておいてください。

```
$ docker-compose up -d
Creating network "mywordpress_default" with the default driver
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
43c265008fae: Already exists
d7abd54d3b34: Pull complete
92b527830a1b: Pull complete
44839710d611: Pull complete
3828a16bed5c: Pull complete
fb91763f6b4e: Pull complete
5fe147754144: Pull complete
2f0de826b14c: Pull complete
0df77a594382: Pull complete
afc0f49ce0c9: Pull complete
b806859ce6f4: Pull complete
Digest: sha256:2333b96e5ebfcbdb20f10654e87f7f4421a0c2d29ff8fbf0696a57055ae1ce7f
Status: Downloaded newer image for mysql:5.7
Pulling wordpress (wordpress:latest)...
latest: Pulling from library/wordpress
43c265008fae: Already exists
6ee27d07994b: Pull complete
d43536f442a0: Pull complete
4d9469dadeb4: Pull complete
4fc33aa1941b: Pull complete
09b922600db1: Pull complete
01805b6582a4: Pull complete
ec43f09bb70c: Pull complete
6568948eed6b: Pull complete
2dc0094a10b5: Pull complete
7142d56062ec: Pull complete
7a44a9f63706: Pull complete
9b7c9a7c3515: Pull complete
59249fc11e6f: Pull complete
31611c57ce32: Pull complete
712c4eef2d95: Pull complete
aaf3860b31ac: Pull complete
b04c02901a3a: Pull complete
eb9dd4eb321b: Pull complete
Digest: sha256:503676370ed3dae3a9f01c086ee1c7d76d683c2e7fcf2ad41f64bb32fd1d0bcd
Status: Downloaded newer image for wordpress:latest
Creating mywordpress_db_1
Creating mywordpress_wordpress_1
```

最初にデータベースのMySQL5.7の公式DockerコンテナイメージをDocker Hubからダウンロードして来て、次にWordPressの公式DockerコンテナイメージをDocker Hubからダウンロードして来ています。
ちなみにこのダウンロードは最初だけですので、手元にDockerコンテナのイメージファイルが既にあれば瞬時に実行されます。
その後にそれぞれ、mywordpress_db_1とmywordpress_wordpress_1の２つのDockerコンテナを作成しています。
プロジェクトの構築ビルド作業が終わったらDockerコンテナの状態をdocker-composeコマンドで確認してみましょう。

```
$ docker-compose ps
         Name                        Command               State          Ports         
---------------------------------------------------------------------------------------
mywordpress_db_1          docker-entrypoint.sh mysqld      Up      3306/tcp             
mywordpress_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8000->80/tcp 
```

2つのDockerコンテナが動作している様子が確認出来ました。
ちなみにdockerコマンドでも確認出来ます。

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
abc123456789        wordpress:latest    "docker-entrypoint.sh"   11 minutes ago      Up 10 minutes       0.0.0.0:8000->80/tcp   mywordpress_wordpress_1
123456789abc        mysql:5.7           "docker-entrypoint.sh"   11 minutes ago      Up 11 minutes       3306/tcp               mywordpress_db_1
```

それでは実際にwebブラウザで確認してみましょう。
今回のプロジェクトでは、TCP/8000番にてWordPressサービスを動作させていますのでポート番号を忘れずに指定しましょう。

```
$ curl localhost:8000
```

正常にビルド構築が出来ていれば、WordPressの初期設定画面が表示されます。

### プロジェクトの停止
プロジェクトの停止もdocker-composeコマンドで一度にすべてのDockerコンテナを停止出来ます。

```
$ docker-compose stop
Stopping mywordpress_wordpress_1 ... done
Stopping mywordpress_db_1 ... done

$ docker-compose ps
         Name                        Command               State    Ports 
-------------------------------------------------------------------------
mywordpress_db_1          docker-entrypoint.sh mysqld      Exit 0         
mywordpress_wordpress_1   docker-entrypoint.sh apach ...   Exit 0  
```

### プロジェクトの起動
停止したプロジェクトを再起動します。すでにビルド構築していますから瞬時に関連するDockerコンテナが起動してサービスが開始されます。

```
$ docker-compose start
Starting db ... done
Starting wordpress ... done

$ docker-compose ps
         Name                        Command               State          Ports         
---------------------------------------------------------------------------------------
mywordpress_db_1          docker-entrypoint.sh mysqld      Up      3306/tcp             
mywordpress_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8000->80/tcp
```

### プロジェクトの削除
使い終わったプロジェクトを削除する場合も、docker-composeコマンドで一度にすべてのDockerコンテナを削除する事が出来ます。

```
$ docker-compose rm
Going to remove mywordpress_wordpress_1, mywordpress_db_1
Are you sure? [yN] y
Removing mywordpress_wordpress_1 ... done
Removing mywordpress_db_1 ... done

$ docker-compose ps
Name   Command   State   Ports 
------------------------------
```

本当に削除するか問い合わせて来ますので、Yと答えると削除実行されます。