vagrant up 一発で立ち上がるウェブアプリケーション開発環境作り　第二回：Docker編

VagrantとDocker（とDocker Compose）を使って開発環境を一発で立ち上げられるようすることを目標とした連載、第二回です。
[第一回：Vagrant編](http://qiita.com/marrontan619/items/01cf11fa74af5bbdd96b)

## Docker Composeとは？

Dockerのコンテナを複数管理しやすくするための、公式ツールです。
どう便利かは、本記事で感じていただけると幸いです。

## 構成

vagrant sshで入ると、/vagrantというディレクトリが存在します。
ホストのVagrantのルートがマウントされているので、ホストでディレクトリを作成したり、ファイルを編集したりできます。

最終的なディレクトリ構成の例はこんな感じ。（あくまで例です）

```
<vagrant-root>
├── docker
│   ├── docker-compose.yml
│   ├── app # アプリコンテナ関連
│   │   ├── Dockerfile
│   │   └── volume
│   │       └── web-root
│   │           └── index.php
│   ├── mysql # DBコンテナ関連
│   │   └── volume
│   │       ├── conf
│   │       │   └── my.conf
│   │       └── sql
│   │           ├── create_database.sql
│   │           ├── create_table.sql
│   │           └── insert_test.sql
│   └── proxy # Webサーバーコンテナ関連
│       └── volume
│           ├── conf
│           │   └── httpd.conf
│           └── log
│               ├── access.log
│               └── error.log
├── package.box
├── provision.sh #第一回参照
└── Vagrantfile
```

```yaml:docker-compose.yml
version: "2"
services:
  # mysql
  mysql:
    image: mysql
    volumes:
      - /vagrant/docker/mysql/volume/sql:/docker-entrypoint-initdb.d:rw
      - /vagrant/docker/mysql/volume/conf:/etc/mysql/conf.d
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: password
  # php
  app:
    build: app/
    volumes:
      - /vagrant/docker/app/volume/web-root:/var/www/html:rw
    environment:
      XDEBUG_CONFIG: remote_host=10.0.2.2
    links:
      - mysql:mysql
  # reverse-proxy
  proxy:
    image: nginx:latest
    volumes:
      - /vagrant/docker/proxy/volume/conf:/etc/nginx/conf.d:rw
      - /vagrant/docker/proxy/volume/log:/var/log/nginx:rw
    ports:
     - "80:80"
     - "443:443"
    links:
      - app:app
```

各コンテナの内容については、今後の連載が続くことを期待してください。（いいねしてもらうと頑張るかもしれません）


## コンテナを立ち上げてみる

docker-compose.ymlがあるディレクトリで、docker-compose upを実行すると、設定内容のコンテナが立ち上がります。

```
cd /vagrant/docker
docker-compose up -d --build
```

## Docker Composeの話

細かい設定内容は各コンテナの回で解説予定なので、DockerとDocker Composeの解説を。

### docker-compose.yml

このファイルに複数コンテナの設定を管理しています。
docker runってオプションが多いし、長いんです。
例えば上記proxyコンテナをdocker runだけで実行しようとすると、

```sh
docker run -d -v /vagrant/docker/proxy/volume/conf:/etc/nginx/conf.d:rw -v /vagrant/docker/proxy/volume/log:/var/log/nginx:rw -p 80:80 -p 443:443 --link app:app <イメージ名>
```

こうなります。
複数コンテナを管理しなくても、これだけで使う価値があるのではないかと。

### docker-compose up

だいたいdocker runです（雑）。docker-compose.ymlの中身を見ています。
--buildのオプションで、docker pull(またはbuild)とを同時に行ってくれます。
ビルドだけ行いたい場合はdocker-compose build。

docker-compose.ymlのservices:の下にある"mysql"、"app"、"proxy"がコンテナ1つにあたります。
引数無しなら、全部のコンテナが対象。
特定のコンテナだけを起動させたいなら、引数にservice名を渡します。

```sh
docker-compose up -d --build app
```

## Dockerの話

設定ファイルをいじって、最初から一発でdocker-compose upが成功するなんて、（少なくとも僕は）滅多にありません。いや、見栄を張りました。絶対にありません。

実際にDockerfileやdocker-compose.ymlを修正し、docker-compose upで試して、反映させていくことになるでしょう。
そんなときのための、Dockerコマンド解説です。
よく使ったコマンドを中心に解説するので、詳細な説明などは公式のドキュメントを参照してください。
https://docs.docker.com/compose/reference/

### コンテナの状態を確認したい

docker psで確認できます。
停止中のコンテナも確認するときは、docker ps -aです。
こんな感じの情報が表示されます。

```
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                    PORTS                                      NAMES
92f398c34cdc        mysql:latest        "docker-entrypoint..."   13 minutes ago      Up 8 minutes              0.0.0.0:3306->3306/tcp                     docker_mysql_1
183d2c9ce713        docker_app          "docker-php-entryp..."   54 minutes ago      Up 8 minutes              9000/tcp                                   docker_app_1
9fc0e107cd09        nginx:latest        "nginx -g 'daemon ..."   2 hours ago         Up 2 seconds              0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   docker_proxy_1
```

docker-composeを使って起動した場合、自動でコンテナに名前を付けてくれます。（container_name: my-web-containerのように、自分で設定も可能）
停止、削除、起動など、この後説明する作業を行いたい場合に補完が効くようにもなるので、docker runで起動する場合も基本的に名前を付けるようにしましょう。
docker runの場合は--nameオプションです。

### コンテナに入って作業したい

attachとexecの2種類方法がありますが、

```sh
docker exec -it <コンテナ名> bash
```

を推奨します。
attachだと、Ctrl+dで抜ける際に、コンテナが停止してしまうからです。
attachはコンテナに入り、execはコンテナに新しいプロセスを注入するという違いがあるためです。
※attachでも、Ctrl+p, Ctrl+qと操作すればコンテナを停止することなく抜けられます。

（本記事の例のように公式のイメージを使ってると、コンテナにエディタも入ってない、ログも標準出力に消えていくetcとなっているので、あまりやることないかも）

### コンテナを作り直したい

環境構築の過程でdocker-compose.ymlを修正した場合は、ここからやり直しです。

dockerコマンドだと、stop→rm→runです。
docker psで取得したNAMES（もしくはCONTAINER_ID）を使います。

```
# 特定のコンテナのみを対象とする場合
docker-compose stop <ymlのサービス名(mysqlなど)>
docker-compose rm mysql
docker-compose up -d mysql

# 管理内の複数のコンテナをまとめて行う場合
docker-compose down
docker-compose up -d

# 特定のコンテナのみを対象とする場合（dockerコマンド版）
docker stop <コンテナ名(docker_mysql_1など)>
docker rm docker_mysql_1
docker run --中略 --name docker_mysql_1 mysql:latest
```

rmに-fオプションを使えば、stopを経なくても削除可能です。

### イメージを作り直したい

環境構築の過程でDockerfileを修正した場合などは、ここからやり直しです。
imageから作成されたコンテナが全て停止していることを前提とします。

```
# 特定のコンテナのみを対象とする場合
docker rmi <イメージ名>
docker run --中略 --name docker_mysql_1 mysql:latest

# 管理内の複数のコンテナをまとめて行う場合
docker-compose down --rmi all
docker-compose up
```

## 結び

Dockerとは？イメージ？コンテナ？など、Dockerにまつわる基本的な用語は飛ばして解説しました。
それらは、もっとわかりやすくまとめてくださってる良記事がたくさんあるので……

次回、[プロキシサーバー編](http://qiita.com/marrontan619/items/1974753500a7e6956318)に続く。