Vagrant を開発用 Web サーバとして利用するときの注意点
罠があるのでまとめておきます。(体験談) なお、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 に関してはこちらに詳細あります。
-
centos - Apache doesn't start after Vagrant reload - Stack Overflow
stackoverflow.com
-
いますぐ実践! Linuxシステム管理
www.usupi.org
ちなみに、これはあくまで CentOS6, apache の際の話です。CentOS7 は Upstart ではなく systemd になったとかいう話を聞いていつつもまだ試せてないので、お試しになった方がいれば @girigiribauer まで教えていただけると嬉しいです。
表示がおかしい、ファイルが途中で途切れる
これも知らずにはまりました。
特に動的にコンテンツを出力しているわけではないのに、途中からファイルが \0 やら謎の文字列やらで埋め尽くされ、どうやら途中で切れているようでした。ざっくり言うとシステムコールのキャッシュに起因する問題のようで、静的なファイルが対象です。
apache の EnableSendfile ディレクティブ を OFF にしておく必要があるので、 自分で用意した Cookbook の場合は、httpd.conf の template に
EnableSendfile Off
を入れておきます。
詳しくは EnableSendfile ディレクティブや sendfile システムコールに関しての詳細はこちら。
-
core - Apache HTTP Server Version 2.2
httpd.apache.org
- 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/ (リンク切れ)
-
hiboma/VirtualBoxのsendfileのバグ.md at master · hiboma/hiboma
memos of experiments, examinations, source reading, ... etc - hiboma/hiboma
github.com
正直、カーネルレベルまで掘り下げて調べてもメリットが少なかったので、あまり掘り下げて理解してません。。。
※ 2015/04/16 追記
nginx では sendfile off; で良さそうですね。
Module ngx_http_core_module
nginx.org
まとめ
このあたりがクリア出来た頃あたりからは、Vagrant 上の開発環境に問題が起きることが少なくなりました。
この辺に対応するだけでグッと使えるようになると思うので、開発環境を本番環境に近づけられるよう設定してみてはいかがでしょうか。