ローカル環境でVagrant+nginxで気軽にリバースプロキシする
サーバーサイドのアプリケーションがあって、静的コンテンツだけHTTPサーバーで配信したいっていうユースケースがあると思います。
サーバー上で動かす場合にはだいたいこんな感じにHTTPサーバーでリバースプロキシしてアプリケーションと静的コンテンツを振り分けますよね。
じゃあ、これをローカルの開発環境のときはどうする?っていう話です。
ローカル環境のホストOSにはHTTPサーバーはたてたくない
ローカル環境で同じことするには、同じようにHTTPサーバーをたてればいいんですが、複数のプロジェクトをかけもちなんかしたりしてるとそれ用のvirtualhostを書いたり、hostsでホスト名を書いたりしてなんかダサい感じになってしまいます。あとは、複数人で開発なんかすると、Windowsの人もいれば、Macの人もいるし、各自色々なプロジェクトもってたりで、こっちでは動くけど、あっちでは動かないとか嫌な感じになります。
そこで、VagrantでHTTPサーバーたてて振り分けられないかなと思って試してみました。
この図の左側みたいに、XAMPPとかでホスト側にHTTPサーバーたてるんじゃなく、右側みたいにVagrantを使ってホスト側はきれいなままにしておきたいっていう気持ちです。このプロジェクトを開発するなら、このVagrantをupするだけみたいにしたい!
右側のVagrantを使ったやつの説明をすると、
- Vagrantで立てた仮想サーバー内にNginxが入っててNginxは80番ポートで待ち受ける
- 仮想サーバーはポートフォワーディングでホストの8000番ポートをゲストのnginxの80番ポートに転送
- 仮想サーバーはVagrantの共有ファイル機能を使って、ホスト側の静的コンテンツをNginxに配信させる
- ホスト側でサーバーアプリケーションを起動(この図の場合はJavaで9000番ポートで起動)
- Nginxは静的ファイル以外のリクエストならホストのJavaアプリケーションにリバースプロキシする
これで、ブラウザからは、http://localhost:8000/
でアクセスすれば、ホスト側のサーバーアプリケーションにつながるし、静的コンテンツはそのまま配信されるという感じ。
これをするなら、Javaのアプリケーションも仮想マシン上で動かしちゃえば?ってことになるんだろうけど、仮想マシンにあんまりメモリとか割り当てたくないし、ホスト側のCPUとかメモリを使いたいなって思ったのでこうしました。
ということで、実際に書いた設定ファイルの説明をしていきます。
Vagrantfile
CentOS6.5でinitする。chef/centos-6.5
vagrant init chef/centos-6.5
Vagrantfileができるので、設定を書き換えます。
ポートフォワーディングの設定と、静的コンテンツを共有フォルダとして、/var/www/html/
におく。プロビジョニングはchef分からないのでシェルです。(chef勉強しないと。。)
# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| # Every Vagrant virtual environment requires a box to build off of. config.vm.box = "chef/centos-6.5" # Create a forwarded port mapping which allows access to a specific port # within the machine from a port on the host machine. In the example below, # accessing "localhost:8080" will access port 80 on the guest machine. config.vm.network "forwarded_port", guest: 80, host: 8000 # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third # argument is a set of non-required options. config.vm.synced_folder "/path/to/your/static/resources/", "/var/www/html" config.vm.provision "shell", path: "provision.sh" end
provision.sh
次に、プロビジョニングするshの内容です。
nginxインストールして、ローカル環境だからとりあえず、ファイアウォール切る。
function install_nginx() { rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm yum -y install nginx cp -f /vagrant/default.conf /etc/nginx/conf.d/default.conf service nginx start chkconfig nginx on } function stop_iptables() { service iptables stop chkconfig iptables off } install_nginx stop_iptables
default.conf (nginx)
nginxの設定ファイルはこのプロビジョニングの時に、cp -f /vagrant/default.conf /etc/nginx/conf.d/default.conf
という感じでこのVagrantfileが置いてある場所にconfを用意しといて上書きする。
ここで、ちょっと一工夫があって、Vagrantで作った仮想サーバーのデフォルトゲートウェイは必ず、10.0.2.2
になるようなので、リバースプロキシ先は、10.0.2.2
としとく。あと、rootは、共有フォルダとしておいた/var/www/html/
。
proxy_buffering off; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_http_version 1.1; upstream playframework { server 10.0.2.2:9000; } server { listen 80; server_name localhost; root /var/www/html; #charset koi8-r; #access_log /var/log/nginx/log/host.access.log main; location / { if (-f $request_filename) { break; } proxy_pass http://playframework; proxy_redirect default; } #error_page 404 /404.html; // 以下省略
これで、ホスト側のブラウザから、http://localhost:8000/
ってアクセスすれば、ホスト側のJavaアプリケーションにつながって、静的ファイルが存在すれば、静的ファイルが配信されます。
まとめ
これで、ホスト側のhostsとか書き換えなくても気軽にリバースプロキシがたてられました!
個人的にこのVagrant+nginx方式のいいところはもっとあって、全ての設定ファイルがソース管理にコミットできることです。しかも、Vagrantで余計なプラグインも入れてないから、Windowsだろうが、Macだろうが、OSのRubyのバージョンがなんであろうと、なんならOSにRubyが入ってなかろうがみんな同じように動くところがとてもいいと思ってます。