Vagrant を開発用 Web サーバとして利用するときの注意点
この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります
罠があるのでまとめておきます。(体験談) なお、box ファイルは CentOS6 ベースのもの、Web サーバは apache です。(本番環境を想定した開発環境なので、nginx は別のところで使っています)
レシピを適用しても上手く表示されない
レシピ適用した後で、 vagrant up
や vagrant reload
などで VM を起動したとしても、Web サーバがうまく動かなかったケースとかありませんでしたか?私はありました。
/var/www を synced folder に指定しているとはまります。
なんともならなかったので、毎回 ssh でログインして sudo service httpd restart
してごまかしてましたが、なんだかはまる人多そうだなーと思ったのでこちらにまとめておきます。
Vagrant の動作順おさらい
レシピの指定を Vagrantfile に書いているケース、knife コマンドを使うケースのいずれにおいても、 vagrant up --provision
もしくは vagrant provision
時に以下のような順序で動作します。(ログ見れば分かりますが)
- box ファイルの設定、仮想マシンの電源ON(ブート処理)
- Vagrant が使う SSH のポートフォワーディング周りの設定
- synced folder の設定
- (Vagrantfile 内に記述があれば)レシピの適用
なお、古いバージョンの Vagrant では、vagrant up
とするだけで up した後に vagrant provision
を実行した時の処理が毎回走っていましたが、最近のやつは vagrant up
するだけでは Vagrantfile 内に書かれたレシピは適用されなくなりました。(こちらが通常だと思います)
なぜ synced folder を Web サーバのドキュメントルートにしてしまった場合にうまく動かないかというと、 1.の段階で Web サービスが起動してしまい(chkconfig など)、3.で行われるはずの synced folder の設定がこの段階では行われておらず、/var/www が無いために Web サービスがうまく動かない、といったことが起きています。
この動作順はどうしようもないので、別の方法を考えなくてはいけません。
Upstart の仕組みを利用する
Upstart というワードをよくご存知の方は、なんとなく予想がつくかと思いますが、 システム起動時に特定のイベントが起きた際、予め指定されたジョブを実行するという仕組みがあります。
Linux は起動時に色々なサービスを立ち上げていますが、 /etc/init
以下に設定ファイルを設置することで、それらを行っています。
今回は、/etc/init/httpd.conf
というファイルを作成し、以下のような内容を記述します。
# start apache on vagrant mounted
start on vagrant-mounted
exec sudo service httpd start
この2行目の vagrant-mounted
というのが、先ほどの Vagrant の動作順の 3. である synced folder の設定に相当するので、こちらのマウントが行われたら、sudo service httpd start
を行う設定です。 ちなみに、/var/www
が無い状態では httpd は起動してないので、restart ではなく start で問題無いようです。
こうすることで、1.の段階で Web サービスの起動に失敗したとしても、3.の直後に Upstart の仕組みによって Web サービスが起動するので、手動で Web サービスの起動などをしなくとも良くなりますね。
Upstart に関してはこちらに詳細あります。
- http://stackoverflow.com/questions/22718785/apache-doesnt-start-after-vagrant-reload
- http://www.usupi.org/sysad/188.html
ちなみに、これはあくまで CentOS6, apache の際の話です。CentOS7 は Upstart ではなく systemd になったとかいう話を聞いていつつもまだ試せてないので、お試しになった方がいれば @girigiribauer まで教えていただけると嬉しいです。
表示がおかしい、ファイルが途中で途切れる
これも知らずにはまりました。
特に動的にコンテンツを出力しているわけではないのに、途中からファイルが \0 やら謎の文字列やらで埋め尽くされ、どうやら途中で切れているようでした。ざっくり言うとシステムコールのキャッシュに起因する問題のようで、静的なファイルが対象です。
apache の EnableSendfile ディレクティブ を OFF にしておく必要があるので、 自分で用意した Cookbook の場合は、httpd.conf の template に
EnableSendfile Off
を入れておきます。
詳しくは EnableSendfile ディレクティブや sendfile システムコールに関しての詳細はこちら。
- http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile
- http://blog.1000k.net/2013/03/20/vm-%E3%81%AE%E5%85%B1%E6%9C%89%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E5%86%85%E3%81%AE-%E9%9D%99%E7%9A%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8C%E6%AD%A3%E3%81%97%E3%81%8F%E3%83%AD%E3%83%BC/
- https://github.com/hiboma/hiboma/blob/master/VirtualBox%E3%81%AEsendfile%E3%81%AE%E3%83%8F%E3%82%99%E3%82%AF%E3%82%99.md
正直、カーネルレベルまで掘り下げて調べてもメリットが少なかったので、あまり掘り下げて理解してません。。。
※ 2015/04/16 追記
nginx では sendfile off;
で良さそうですね。
http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile
まとめ
このあたりがクリア出来た頃あたりからは、Vagrant 上の開発環境に問題が起きることが少なくなりました。
この辺に対応するだけでグッと使えるようになると思うので、開発環境を本番環境に近づけられるよう設定してみてはいかがでしょうか。
この記事は書かれてから1年以上が経過しており、最新の情報とは異なる可能性があります