nginx + unicorn + Rails on Mac
とりあえず動かしてみたのでメモ。
unicornを動かす
まずはgemをインストール。
$ gem install unicorn
unicornの処理を設定する
$ cd <RAILS_ROOT> $ vi config/unicorn.rb
<RAILS_ROOT>/config/unicorn.rbはこんな感じ(nginx + unicorn を試してみたからほぼそのまま拝借):
# ワーカーの数 worker_processes 2 # ソケット経由で通信する listen File.expand_path('tmp/sockets/unicorn.sock', ENV['RAILS_ROOT']) # ログ stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT']) stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT']) # ダウンタイムなくす preload_app true before_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! old_pid = "#{ server.config[:pid] }.oldbin" unless old_pid == server.pid begin # SIGTTOU だと worker_processes が多いときおかしい気がする Process.kill :QUIT, File.read(old_pid).to_i rescue Errno::ENOENT, Errno::ESRCH end end end after_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end
そして起動。
$ unicorn_rails -c config/unicorn.rb -E production -p 5000 -D
unicorn_railsはRailsアプリケーションをunicornで起動するためのコマンド。最近のRailsはRackに乗っかっているからunicornコマンドだけでも十分だけど、unicorn_railsならではのメリットもあるらしい(さくらの VPS に登録してみた(4) nginx + unicorn参照)。
-cオプションで設定ファイルを指定、-EでRAILS_ENVを指定(デフォルトはdevelopment)、-pでポートを指定(デフォルトは8080)、-Dでデーモンとして動作。それ以外については-hオプションで一覧が表示される。
nginxを動かす
まずHomebrewでインストールして起動。
$ brew install nginx $ cp /usr/local/Cellar/nginx/1.0.4/org.nginx.nginx.plist ~/Library/LaunchAgents/ $ launchctl load -w ~/Library/LaunchAgents/org.nginx.nginx.plist
この時点で http://localhost:8080 にアクセスするとnginxの初期画面が表示されるはず。
apacheでいうところのconf的なものは/usr/local/etc/nginx以下に入れられる。 さて、設定。
$ cd /usr/local/etc/nginx $ mkdir -p sites-available sites-enabled $ vi nginx.conf $ vi sites-available/default $ ln -s /usr/local/etc/nginx/sites-available/default sites-enabled/default
まずは初期画面に関する設定をnginx.confからsites-available/defaultに書き写す。
nginx.confの差分:
@@ -32,87 +32,6 @@ http { #gzip on; - server { - listen 8080; - server_name localhost; - - #charset koi8-r; - - #access_log logs/host.access.log main; - - location / { - root html; - index index.html index.htm; - } - - #error_page 404 /404.html; - - # redirect server error pages to the static page /50x.html - # - error_page 500 502 503 504 /50x.html; - location = /50x.html { - root html; - } - - # proxy the PHP scripts to Apache listening on 127.0.0.1:80 - # - #location ~ \.php$ { - # proxy_pass http://127.0.0.1; - #} - - # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 - # - #location ~ \.php$ { - # root html; - # fastcgi_pass 127.0.0.1:9000; - # fastcgi_index index.php; - # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; - # include fastcgi_params; - #} - # deny access to .htaccess files, if Apache's document root - # concurs with nginx's one - # - #location ~ /\.ht { - # deny all; - #} - } - - - # another virtual host using mix of IP-, name-, and port-based configuration - # - #server { - # listen 8000; - # listen somename:8080; - # server_name somename alias another.alias; - - # location / { - # root html; - # index index.html index.htm; - # } - #} - - - # HTTPS server - # - #server { - # listen 443; - # server_name localhost; - - # ssl on; - # ssl_certificate cert.pem; - # ssl_certificate_key cert.key; - - # ssl_session_timeout 5m; - - # ssl_protocols SSLv2 SSLv3 TLSv1; - # ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; - # ssl_prefer_server_ciphers on; - - # location / { - # root html; - # index index.html index.htm; - # } - #} - + include /usr/local/etc/nginx/sites-enabled/*; }
末尾の追加項目は、nginx.confにべた書きするのではなく、sites-enabled/以下に分割されたファイルを読み込むように設定するための記述である。 sites-available/defaultは次のようにした。
+server { + listen 8081; + server_name localhost; + + location / { + root html; + index index.html index.htm; + } +} +
もともとは8080をlistenしていたが、Railsアプリのほうに8080を使いたかったのでここではとりあえず8081にした。
root html;
はドキュメントルートをhtmlディレクトリ(ここでは/usr/local/Cellar/nginx/<VERSION>/htmlになる)に設定している。
ここまでやって文法にミスが無ければnginxを再起動して、 http://localhost:8081 にアクセスしてみる。
$ /usr/local/sbin/nginx -t # 文法チェック $ launchctl unload ~/Library/LaunchAgents/org.nginx.nginx.plist $ launchctl load ~/Library/LaunchAgents/org.nginx.nginx.plist
nginxとunicornをつなぐ
次にunicornとつないでRailsアプリを表示してみる。
$ vi sites-available/<APPNAME>-unicorn $ ln -s /usr/local/etc/nginx/sites-available/<APPNAME>-unicorn sites-enabled/<APPNAME>-unicorn
upstream <APPNAME>-unicorn { server unix:/path/to/RAILS_ROOT/tmp/sockets/unicorn.sock; } server { listen 8080; server_name localhost; root /path/to/RAILS_ROOT/public; access_log /path/to/RAILS_ROOT/log/access.log; error_log /path/to/RAILS_ROOT/log/error.log; location / { if (-f $request_filename) { break; } # ファイルが存在しなければunicornにproxyする 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://<APPNAME>-unicorn; } # この記述がないと静的ファイルが表示されなかった location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ { expires 1y; } }
ここまでやって文法にミスが無ければnginxを再起動して、 http://localhost:8080 にアクセスしてみる。
$ /usr/local/sbin/nginx -t # 文法チェック $ launchctl unload ~/Library/LaunchAgents/org.nginx.nginx.plist $ launchctl load ~/Library/LaunchAgents/org.nginx.nginx.plist
最後に
とりあえず動いた。
以下、気になる点:
- ApacheとNginx、PassengerとUnicorn、どっちがどういいんだろう?
- 再起動するためにlaunchctlを呼ぶのは面倒くさい、なにか適当なコマンドはないのかな?
- passengerのnginxモジュールを入れるためにはnginxを再コンパイルする必要があるみたいで、そうなるとRVMでgemsetを自由に切り替えられる環境とは相性が悪いのでは(本番ではRVMを使わないから関係ないだろうけど)
- nginxの設定ファイルのセミコロンが面倒くさい
ちなみに今回なぜ80を使わずに808xを使ったかというと、powが80を奪ってしまっているから。Apacheに関してはIPv6で動かして回避するという方法があるらしいけど、nginxはどうなんだろう?