リバースプロキシ経由でDancerを動かす方法

VPSなどで同一ホストに複数のWebアプリをデプロイしたいとき、ドメインは同じでサブディレクトリ毎にアプリのルートを割り当てるということをよくやると思う。PHPmod_perl等を使ってApacheの中で動かすことも一般的だが、最近はapacheまたはnginxなどの高速なWebサーバをリバースプロキシとして動かし、本体の処理はローカルでマルチコアを上手く使いこなすWebコンテナ(そういうのをプリフォークサーバと呼ぶらしい)でさばくというのが流行らしい。

それをPerlの軽量WAFであるDancerでやったのでメモ。

Apacheの設定

例えばhttp://xx.xx.xx.xx/foo/barをアプリのルートにしたい場合、HTTPリクエストヘッダのX-Request-Hostにxx.xx.xx.xx、
request-baseに/foo/barが入ってることをDancerのリバースプロキシ用プラグイン(Dancer::Plugin::ProxyPass)は要求する。
X-Request-Hostはmod_proxyがつけてくれるっぽいがrequest-baseのほうはつけてくれないのでmod_headersを使って自分で追加する。ローカルで動く本体のサーバのポートが5000の場合は以下のようになる。(allow from allのところは必要に応じて変えてください)


  Order deny,allow
  allow from all


    RequestHeader set request-base /foo/bar
    ProxyPass http://localhost:5000
    ProxyPassReverse http://localhost:5000

proxy_httpとheadersをa2enmodしてなければして、apacheを再起動

# a2enmod proxy_http headers
# service apache2 restart

Dancer側での扱い

Dancer::Plugin::ProxyPassではproxy->uri_for()というメソッドがあり、TemplateToolkitの中でも[% proxy.uri_for('subdir') %]という感じで使うことができる。このメソッドはリバースプロキシ経由でない時(ヘッダに項目がないとき)は通常のパス指定にフォールバックするので、そのままスタンドアロンでも動かせる。

なので以下でproxy.uri_forを使うように書き換える。

  • コントローラ(lib/$YourDancerApp/App.pm)の中でredirectするところ
  • viewのテンプレートファイルの中の以下のようなタグで相対パスを指定するところ
    • script src="xxx"
    • link href="xxx"
    • a href="xxx"
    • img src="xxx"
    • form action="xxx"
    • などなど

例えば(TTを使ってる場合)

# layout/main.tt
(中略)
<link rel="stylesheet" href="[% proxy.uri_for('/') %]css/style.css" />
(中略)
<script src="[% proxy.uri_for('/') %]javascript/jquery.js" />
(略)
# lib/YourDancerApp/App.pm
(中略)
use Dancer::Plugin::ProxyPath;

(中略)

get '/hoge' => {
  redirect proxy->uri_for('/');
};

(中略)

などとする。

ローカル側の本体サーバ

Plackupを起動するところは通常と同じ。

# cd $YourDancerAppDir
# nohup plackup bin/app.pl &

というわけで

Dancerは便利です。