nginx+Unicornでサブディレクトリでアプリを動かす
Passengerだと簡単だったけどUnicornだとちょっと手こずった。
nginx側
ディレクトリの準備
nginxのroot以下に任意の名前のサブディレクトリを作る。
これはRalisアプリケーションのpublicディレクトリのシンボリックリンクにする。
cd /var/www/root ln -s /var/www/my-app/current/public my-app
(Capistranoを使っているのでこの例ではcurrentがついている)
nginxの設定
nginxのupstreamとserverの設定を抜粋。
upstream unicorn-of-my-app { server www.example.com:8080; } server { listen 80; server_name www.exemple.com root /var/www/root; error_log /var/www/my-app/current/log/error.log; location /my-app { try_files $uri $uri.html $uri/index.html @unicorn-of-my-app; } location @unicorn-of-my-app { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://unicorn-of-my-app; } }
location /my-app の部分は静的ファイルがあればnginxが返すようにtry_files。
ファイルがなければリクエストをunicorn-of-my-appに投げる。
config.ruの修正
以下のように修正する。
Unicornが/my-appの部分もパスとして受け取るので、その辺りを考慮してルーティングしてやる。
ifで分岐させたのは開発時にはサブディレクトリで開発しないだろうから。
if ENV['RAILS_RELATIVE_URL_ROOT'] map ENV['RAILS_RELATIVE_URL_ROOT'] do run MyApp::Application end else run MyApp::Application end
またはconfig.ruをすっぱり削除してもいい。
config.ruがない場合はUnicornがよきにはからってくれる。
config.ruがある場合はconfig.ruの内容をそのまま使うので、上記のように自前で面倒を見ないといけない。
わざとそうしてるのか、単に気が利かないだけなのかちょっと意図が不明。
気が利かないだけの方なら将来的にはこの手順はいらなくなるかも。
Unicornの起動
bundle exec unicorn_rails -E production -D --path /my-app
–pathで指定したパスがさっきのconfig.ruで使ったENV[‘RAILS_RELATIVE_URL_ROOT’]に入る。
さて、これでサブディレクトリでRailsアプリが有効になったはず。
その他
- sub directoryではなくsub uriの方が検索性がよかった
- config.action_controller.relative_url_rootを使う方法はDeprecated?
- config.ruとかいじらなくてもnginxのrewriteだけで一瞬うまくいくかと思ったが、link_toやurl_forが全滅していた
- nginx+Passengerでもいいならそっち使った方がかなり楽
しかしこの件について情報がなさすぎだったんだが、あえて言うほどでもない基本的な見落としがあるのだろうか。