Laravel開発環境をhhvm + nginx + Debian + Docker + Vagrantで作る

※ ホストOSはUbuntu 14.04 LTSで行っています。
　 他のOSでは適宜読み替えてください。作業内容はほぼ一緒・・・のはず。

##専用ディレクトリ作成

最初にテスト用に専用ディレクトリを作成しました。
今回は ~/projects/vm を作ったのでそこに。

    mkdir ~/projects/vm
    cd ~/projects/vm

以降はこのディレクトリをVagrantfileがあるディレクトリ "./" として表記します。


##Vagrantfile作成

DebianのVagrantfileを作成。

```rb
    Vagrant.configure(2) do |config|
        config.vm.box = "debian/jessie64"
        config.vm.network "private_network", ip: "192.168.33.11"
        config.vm.synced_folder ".", "/vagrant", id: "core", :nfs => true, :mount_options => ['nolock,vers=3,udp']

        config.vm.provision "shell", path: "vagrant_provision.sh"

        config.vm.provision "docker" do |d|
            d.build_image "/vagrant", args:"-t vm"
            d.run "vm", args: "-d -p 80:80 -p 2812:2812 -v /vagrant:/vagrant"
        end
    end
```

一行ずつ解説を入れてみます。

    config.vm.box = "debian/jessie64"
        debian/jessie64というVagrant boxを使いますよという宣言。
        jessie64は、Debian 8の64bit版の指定です。
        Debian 8の最新版がインストールされます。

    config.vm.network "private_network", ip: "192.168.33.11"
        ネットワーク設定でIPアドレスを割り振っています。

    config.vm.synced_folder ".", "/vagrant", id: "core", :nfs => true, :mount_options => ['nolock,vers=3,udp']
        共有ディレクトリの指定です。
        "."がVagrantfileがあるディレクトリ "./" を指定する記述で、それをゲストOS上では"/vagrant"ディレクトリとして使えるように設定しています。
        ホストOSでNFSサーバが動作している必要があります。
        NFSサーバは sudo apt-get install nfs-kernel-server でインストール。

    config.vm.provision "shell", path: "vagrant_provision.sh"
        provisionというVagrantの機能を使って、ゲストOS起動前に動作設定を行います。
        素の状態の debian/jessie64 Vagrant boxでは、/usr/lib/apt/methods/https が見つからないと言われてdockerのインストールがコケてしまうので、それを改善するシェルスクリプトを読み込んでいます。

    config.vm.provision "docker" do |d|
        d.build_image "/vagrant", args:"-t vm"
        d.run "vm", args: "-d -p 80:80 -p 2812:2812 -v /home/core/share:/home/core/share"
    end
        同じく今度はdockerのprovision。こちらではdockerのビルドと起動を行っています。

        d.build_image "/vagrant", args:"-t vm"
            ゲストOS（Vagrant）上の/vagrantディレクトリ、つまりホストOS上（筆者の場合Ubuntu）での "./" にあるDockerfileを使ってdockerイメージをビルドします。
            -t vmでビルドするdockerイメージにvmというタグ名を振っています。
            以降このvmというタグ名でdockerイメージにアクセスできるようになります。

        d.run "vm", args: "-d -p 80:80 -p 2812:2812 -v /vagrant:/vagrant"
            前行でビルドしたvmというタグ名のdockerイメージを起動しています。

            -d はバックグランドで動作させる指定

            -p 80:80 は、Vagrant上のOSの80番ポートとdocker上のOSの80番ポートを転送設定して、Vagrant:80にアクセスがあったらdocker:80が動作するように。

            -p 2812:2812はmonitのweb GUIの使用ポートです。

            -v /vagrant:/vagrant はVagrant - docker 間の共有ディレクトリ設定です。
            docker上で/vagrantにアクセスすると、Vagrant上の/vagrantにアクセスできます。
            さらにVagrant上の/vagrantはホストOSの "./" と共有設定しているため、dockerの/vagrantがホストOSの "./" と直結します。

途中で出てきたvagrant_provision.shの内容は以下

    sudo apt-get update
    sudo apt-get install -y apt-transport-https


##Dockerfile作成

次にDockerfileを作成。

nginxの最新版が入っているdockerイメージをベースに指定します。
これでnginxインストール分の記述を浮かそうという魂胆です。

    FROM nginx
    CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

ひとまずこの2行で、nginxが動くことを確認します。

##nginxのみで動作確認

vagrant upして、ブラウザから http://192.168.33.11/ へアクセス。

    vagrant up

Welcome to nginx!が表示されればOKです。

筆者はvagrantをいくつも起動していたせいで、「80番ポートが使われててvagrant upが出来ません」（意訳）みたいなエラーで悩みました。
他のvagrantイメージが動いているか確認して、不要なものは落としておきましょう。。。


######vagrantの状態確認
    vagrant status

または
    vagrant global-status

######vagrantをシャットダウン
    vagrant halt


##hhvmインストール（with monit）

それでは、Dockerfileにhhvmのインストールの記述をします。

このイメージはDebianがベースになっているようなので、
hhvmもDebian用のものをインストールしています。
（他OS用の記述ではうまく動作せず、Debian用の記述なら起動動作とも支障なく動いています）

そして、dockerは1コンテナでは1サービスしか動作しないため、
そのままではnginxとhhvmを同時に動作させることが出来ません。

そこでメインで動作させるサービスとして、サービス監視ツールのmonitをインストールし、
monitからnginxとhhvmを起動＋監視してもらいます。

```Dockerfile
FROM nginx:1.9

RUN mkdir /etc/nginx/sites-available &&\
    mkdir /etc/nginx/sites-enabled &&\
    touch /etc/nginx/sites-enabled/default

RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449
RUN echo deb http://dl.hhvm.com/debian jessie main | tee /etc/apt/sources.list.d/hhvm.list
RUN apt-get update
RUN apt-get install -y hhvm
RUN /usr/share/hhvm/install_fastcgi.sh

COPY assets/nginx.default.conf /etc/nginx/sites-available/default.conf
RUN sed -i "s/.*conf\.d\/\*\.conf;/&\n    include \/etc\/nginx\/sites-enabled\/\*;/" /etc/nginx/nginx.conf
RUN unlink /etc/nginx/sites-enabled/default
RUN ln /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/default
RUN mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.original

RUN apt-get install -y monit
COPY assets/monit.monitrc /etc/monit/conf.d/monitrc
COPY assets/monit.nginx.conf /etc/monit/conf.d/nginx.conf
COPY assets/monit.hhvm.conf /etc/monit/conf.d/hhvm.conf

CMD ["/usr/bin/monit", "-I", "-c", "/etc/monit/monitrc"]
#CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
```

また、そのままではinstall_hhvm.shが正常に動作しないため、
/etc/nginx/sites-available
/etc/nginx/sites-enabled
/etc/nginx/sites-enabled/default
を作成するようになっています。

更に、事前に各種設定ファイルをassetsディレクトリに置いておくと、
dockerコンテナの該当ディレクトリにコピーしてくれるようにしてあります。
（このへんはGitHubにアップしてあるファイルを確認してください。GitHubについては後述）


##Vagrant再起動

Dockerfileを書き換えた場合は、Vagrantのリロードとdockerイメージのリビルドが必要です。

    vagrant reload
    vagrant provision

一度に済ませられる便利コマンドがこちら。

    vagrant reload --provision

画面に表示される処理履歴が早くて追い切れないとか、長すぎて最初の方のログ消えてるとかあるので、そういう場合はログファイルに出力すると後からゆっくり読めます。
Dockerfileの記述をトライ＆エラーする時に便利。

    vagrant reload --provision >> provision.log

ただし、assetsディレクトリ内のファイルを書き換えた場合は、vagrant provisionしても変更が反映されないようなので、Vagrantイメージを破棄して再生成する必要があるようです。

######Vagrantイメージの破棄
    vagrant destroy

######Vagrantイメージの生成
    vagrant up


##hhvm動作確認

共有ディレクトリとして設定した "./" のwww/html/laravel/publicディレクトリをnginxのドキュメントルートとして設定してあり、そこにphpinfo.phpが最初から置いてありますので、http://192.168.33.11/phpinfo.php にアクセスすると、phpinfoそっくりのhhvmの環境情報の表示が出ます。
これでhhvmの動作確認も完了。

ちなみに http://192.168.33.11:2812/ でmonitもログインできます。
初期ID/パスはadmin/monitで設定してあるので、ないと思いますが本番環境で使う際は必ず変更してください。
nginxとhhvmで動作があやしい時はmonitからサービスを再起動するとわりと直ったりします。

##Laravelインストール＋動作確認

composerを使ってインストールするので、入っていない場合はまずcomposerからインストールします。

    sudo apt-get install composer

Laravelは ./www/html でcomposer create-projectコマンドでインストールします。

    cd ./www/html
    composer create-project laravel/laravel


http://192.168.33.11/ にアクセスして、"Laravel 5"の表示が出ることを確認したら完了です。


##おわりに

Vagrantとdocker使ってhhvmでLaravel動かしたかったんや・・・


##GitHub

今回作成したVagrantfileおよびDockerfileと付属のファイルをGitHubに置いてあります。

    git clone http://github.com/mkgask/vm

して

    vagrant up

すれば動きますが、Laravelは入ってないので、"./"で

    composer create-project laravel/laravel

してください。

あとDBも入れてないので、SQLiteを使うかDockerfile書き換えてインストールするなどしてご自由にどうぞ。