vagrant と Docker for Mac で、いい感じの開発環境を構築する

# 仕様
- web用・DB用と、2つのコンテナを1つの```Vagrantfile```にて定義しています。
- ```vagrant up/halt```にて2つのコンテナは同時に起動・停止します。
- ホスト（Mac）上のディレクトリを、web用コンテナ上の(Webサーバーの)ドキュメントルートにマウントし、ホスト（Mac）から直接、編集・更新ができます。

# 準備
## DockerImageの用意
- WEB用、DB用のDockerイメージを用意します。
- WEB用はDockerHUB上の[centOS](https://hub.docker.com/_/centos/)を元に構築
- DB用はDockerHUB上の[mysql](https://hub.docker.com/_/mysql/)そのまま利用

### WEB用Dockerイメージのサンプル

- Dockerfile

```
FROM centos:centos6

#Set root password
RUN echo "root:hogehoge" | chpasswd

# Update All
RUN yum update -y

# Install & Add repo
RUN yum install openssh-server -y
RUN rpm -Uvh http://ftp.riken.jp/Linux/fedora/epel/epel-release-latest-6.noarch.rpm
RUN rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
RUN yum --enablerepo=epel install monit -y

# For monit config
ADD monit/sshd.conf  /etc/monit.d/sshd.conf
ADD monit/apache.conf /etc/monit.d/apache.conf
RUN sed -ri 's/use address localhost/use address 0.0.0.0/g' /etc/monit.conf
RUN sed -ri 's/allow localhost/# allow localhost/g' /etc/monit.conf

# Install PHP5.6 & Apache
RUN yum --enablerepo=remi-php56 install php php-devel php-gd php-xml php-mbstring php-opcache php-mcrypt php-mysqlnd php-pecl-apcu php-pecl-memcached -y

# Apache config
RUN sed -ri 's/#NameVirtualHost *:80/NameVirtualHost *:80/g' /etc/httpd/conf/httpd.conf
ADD apache/00_virtualhost.conf /etc/httpd/conf.d/00_virtualhost.conf

# Clear yum cache
RUN yum update all -y

# for ssh
EXPOSE 22
# for WEB
EXPOSE 80
# for monit
EXPOSE 2812
CMD ["/usr/bin/monit", "-I", "-c", "/etc/monit.conf"]
```

- monit/sshd.conf

```
check process sshd with pidfile /var/run/sshd.pid
    start program = "/sbin/service sshd start"
    stop program = "/sbin/service sshd stop"
```

- monit/apache.conf

```
check process apache with pidfile /var/run/httpd/httpd.pid
    start program = "/sbin/service httpd start"
    stop program = "/sbin/service httpd stop"
```

- apache/00_virtualhost.conf

```
<VirtualHost *:80>
    ServerName   localhost
    ErrorLog     /var/log/httpd/localhost-error_log
    CustomLog    /var/log/httpd/localhost-access_log common

    DocumentRoot /var/www/public_html
    <Directory "/var/www/public_html">
      AllowOverride All
      Options FollowSymLinks
      Options -Indexes
    </Directory>
</VirtualHost>
```

### DockerImageの作成
```
docker build -t web:apache ./ --no-cache=true
```
```
docker pull mysql:5.6
```

# Vagrantfile

```
Vagrant.configure("2") do |config|

  config.vm.define "db01" do |node|
    node.vm.provider "docker" do |d|
      d.force_host_vm = false
      d.remains_running = false
      d.name = "db01"
      d.image = "mysql:5.6"
      d.ports = ["3306:3306"]
      d.env = {
        MYSQL_ROOT_PASSWORD: "root"
      }
    end
  end

  config.vm.define "web01" do |node|
    node.vm.synced_folder "public_html", "/var/www/public_html"
    node.vm.provider "docker" do |d|
      d.force_host_vm = false
      d.remains_running = false
      d.name =  "web01"
      d.image = "web:apache"
      d.ports = ["22122:22","80:80","2812:2812"]
      d.link "db01:db01"
    end
  end

end
```

## 解説
### [config.vm.define "db01" / "web01" do |node|]
- 複数のコンテナを立ち上げるため、各コンテナを定義

### [node.vm.provider "docker" do |d|]
- Vagrant DockerProvider の指定

### [d.force_host_vm = false]
- Vagrant DockerProvider を利用する場合、Mac環境ではDockerホスト用のVagrantBox(boot2docker)が自動的にダウンロード・起動されます。今回はDocker for Mac を利用するため```false```とし、Boxを利用しません。詳しくは[こちら](https://www.vagrantup.com/docs/docker/configuration.html#force_host_vm)

### [d.ports = ["3306:3306"] / ["22122:22","80:80","2812:2812"]]
- 各コンテナで[フォワード先のポート：(コンテナで)解放するポート]を指定　

### [node.vm.synced_folder "public_html", "/var/www/public_html"]
- ホスト(Mac上)のVagrantfileがあるカレントディレクトリ内の```public_html```を、コンテナ上の```/var/www/public_html```にマウント
- Vagrant を利用すると、Mac上のカレントディレクトリがコンテナ上の```/vagrant```にマウントされますが、あえて明示的に指定

### [d.link "db01:db01"]
- web01コンテナとdb01をリンク
- web01からは、ホスト名```db01```にてdb01に接続が可能

### [MYSQL_ROOT_PASSWORD: "root"]
- MySQLでのrootユーザーのパスワードの設定

### その他
- web01のDockerイメージは、Apacheのドキュメントルートを```/var/www/public_html```と設定

# コンテナの起動
1. ```Vagrantfile```と同じディレクトリ内に```public_html```を用意
2. ```vagrant up --no-parallel```を実行します。
    3. Vagrantfile内に複数のVM(コンテナ)が記載されている場合、Vagrantは標準でパラレル(同時進行)でVMを起動させます。
今回、コンテナ間のリンクを利用するため、web01コンテナよりも先にdb01コンテナの起動が完了している必要があります。
そのため、```--no-parallel```を付け、コンテナを順に起動させます。
    4. db01コンテナをVagrantfile上で先に書くこと。
    5. 詳しくは[こちら](https://www.vagrantup.com/docs/cli/up.html#_no_parallel)
3. ブラウザから```localhost```を開くと```public_html```に設置したファイルが観れます。
4. PHPプログラム（web01コンテナ）からDBを参照する場合は、ホスト名に```db01```を指定ください。
5. ホスト（Mac）上からDBを参照する場合は、```127.0.0.1:3306```にて参照可能です。 

# まとめ
今までのboot2dockerイメージを利用した、VagrantでのDockerコンテナの利用の場合、Mac上のディレクトリをDockerホストと共有し、Dockerコンテナにマウントする手順となっていました。
Docker for Mac を利用すれば、Mac上のディレクトリを直接Dockerコンテナにマウント出来るようになりシンプルな構成となりました。
Vagrantを利用することで、複数のコンテナの起動停止が1つのコマンドで可能です。
おそらくDocker for Windows でも流用可能かと思います。


# 追記

その後、しばらく使ってみていくつかの軽微な不具合があります。

## synced folder が毎回更新されていると認識される

2回目以降の起動時に、```synced folder```が更新されていると認識され、コンテナの起動時にコンテナが再作成されている。

```
$ vagrant up --no-parallel
Bringing machine 'db01' up with 'docker' provider...
Bringing machine 'web01' up with 'docker' provider...
==> db01: Starting container...
==> db01: Provisioners will not be run since container doesn't support SSH.
==> web01: Vagrant has noticed that the synced folder definitions have changed.
==> web01: With Docker, these synced folder changes won't take effect until you
==> web01: destroy the container and recreate it.
==> web01: Starting container...
==> web01: Provisioners will not be run since container doesn't support SSH.
```

- 原因は謎です。


## コンテナのステイタスが正しく反映されない

2回目以降の起動時に```vagrant global-status```にて正しくコンテナの起動状態が取得できません。

```
$ vagrant global-status
id       name    provider      state       directory
------------------------------------------------------------------------------------------
0671d78  web01   docker        stopped     /Users/hogeuser/Documents/vagrant/docker_webdb
d69b340  db01    docker        stopped     /Users/hogeuser/Documents/vagrant/docker_webdb
```

※実際にはコンテナは起動している

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
5e5e7816bee9        web:apache24        "/bin/sh -c '/usr/sbi"   11 minutes ago      Up 7 minutes        0.0.0.0:80->80/tcp       web01
20845bd63177        mysql:5.6           "docker-entrypoint.sh"   12 minutes ago      Up 7 minutes        0.0.0.0:3306->3306/tcp   db01
```

その際は```$ vagrant global-status --prune```コマンドで正しいステイタスが取得できます。

```
$ vagrant global-status
id       name    provider      state       directory
------------------------------------------------------------------------------------------
0671d78  web01   docker        running     /Users/hogeuser/Documents/vagrant/docker_webdb
d69b340  db01    docker        running     /Users/hogeuser/Documents/vagrant/docker_webdb
```