Rails3アプリをnginx+unicornで動かしたら速すぎた
いやぁ・・・Rails3はいいですね(`・ω・´) b
Rails2とはなんだったのか・・・というレベルの完成度で、
なんとなく納得しないままRails2を使っていた私も、
Rails3になってからはバリバリに使いまくりです*1
そんなRailsを動かすAppサーバとして、
以前から定番になっていたのがpassengerでして、
私もApacheやnginxと組み合わせて使ってました*2
ただ、最近よく耳にするのがnginxにunicornを組み合わせた構成です
前々から気になっていたものの、なかなか手をつけられなかったのですが、
仕事でもプライベートでもちょうどRails3アプリをリリースするタイミングだったので、
nginx+unicornの環境を試してみました
なお、非常に細かな解説がある良記事がありますので、
ぜひそちらを先に(´・ω・)っ
次世代RailsサーバーUnicornを使ってみた « BPS株式会社 開発ブログ Beyond Perspective Solutions LTD.
環境
- /path/to/app にアプリの実体があるとする
- nginxは /usr/local/nginx にインストール
- サーバ名はhogehoge.piyo
- unicornのポートは8080
nginxのインストール
ソースからmakeしてもいいのですが、
今回はpassenger経由で入れてみました
後々passengerに切り替える場合でも楽ですし・・・
途中、デフォルトインストールか細かいconfigureを使うか聞かれますが、
デフォルトでもprefixの指定はできるので問題ないかと
このやり方だと、nginx.confにpassenger絡みの記述が追加されますが、
コメントアウトすればOKです
unicornのインストールと起動
gemなのでインストールは簡単です
「gem install unicorn」でもいいのですが、
Gemfileに「gem 'unicorn'」を追加して「bundle install」の方が、
Rails3としては正しいかと
$ cd /path/to/app $ vi Gemfile # 「gem 'unicorn'」を追加 $ bundle install $ unicorn_rails # -D でデーモン化 -E でRAILS_ENV指定 -c でconfig
・・・と、これで起動してくれればいいのですが、
rackに関するエラーが出る場合がありますΣ(゚Д゚)ガーン
この場合、bundleを経由して実行する必要があります
(rspecの単体起動と同じ)
$ bundle exec unicorn_rails
本番サーバで起動する場合も同じ手段がいるかもしれません
これで起動が確認できたら、RAILS_ROOT/config/unicorn.rb あたりに、
unicornの設定を書いておきます
さっきのサイトだとあまりに細かすぎるので、
このあたりを参考に(´・ω・)っ
http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
http://d.hatena.ne.jp/milk1000cc/20100804/1280893810
私はminimalをベースに、before_fork / after_forkを付け加える感じにしました
あとはconfig指定で動かして確認してみましょう
$ cd /path/to/app $ bundle exec unicorn_rails -E production -c config/unicorn.rb
オプションに-DをつけなければCTRL+Cで止められます
initスクリプトは以下を参考にしました
基本的にアプリ単位でのスクリプトになります
https://gist.github.com/308216
念のためunicorn_railsをbundle exec経由に変更しました
nginx+unicorn連携
実はunicornはあまり関係なくて、
nginxでproxyを書くのにどうするかって話ですが、
ポイントは静的ファイルの扱いです
単純にunicornへリクエストを流そうとすると、
CSSやJSファイルが見つかりませんΣ(゚Д゚)ガーン
まあ、当然の動作ですが・・・
そんなわけでconfigはこんな記述に
upstream app.hogehoge.piyo { server 127.0.0.1:8080; } server { listen 80; server_name hogehoge.piyo; location ~* \.(html|ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ { root public; break; } location / { if (-f $request_filename) { break; } 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://app.hogehoge.piyo; } }
ちなみに、「root public」はRails3アプリのpublicを指しています
# ln -s /path/to/app/public /usr/local/nginx/public
なので、いちいちどこかにファイルをコピーしなくてもOKです
もちろん、一つのサーバで複数動かす場合はpathを工夫してください