はじめに
NginxとUnicornでRailsサーバーを構築する必要が出てきたので、その時のメモを残しておきます。
この後Nginxと接続に関する記事を書いて、最終的にCapistranoでアップする手順を記載します。
注意
僕は環境周りがとても苦手なので、以下の点に関して誤っている点があるかもしれません。
Unicornのインストール
Unicornのインストールは以下をGemfileに記載してbundle install
で行います。
gem 'unicorn'
Unicornの設定ファイル
Unicornの設定ファイルは大体以下のようになります。
説明は設定ファイル内にコメントとして記載してます。
参考:
Rails4.2 を Nginx + Unicorn で動作させる
# Railsのルートパスを求める。(RAILS_ROOT/config/unicorn.rbに配置している場合。)
rails_root = File.expand_path('../../', __FILE__)
# RAILS_ENVを求める。(RAILS_ENV毎に挙動を変更したい場合に使用。今回は使用しません。)
# rails_env = ENV['RAILS_ENV'] || "development"
# 追記に記載してます。入れた方がいいです。
ENV['BUNDLE_GEMFILE'] = rails_root + "/Gemfile"
# Unicornは複数のワーカーで起動するのでワーカー数を定義
# サーバーのメモリなどによって変更すること。
worker_processes 2
# 指定しなくても良い。
# Unicornの起動コマンドを実行するディレクトリを指定します。
# (記載しておけば他のディレクトリでこのファイルを叩けなくなる。)
working_directory rails_root
# 接続タイムアウト時間
timeout 30
# Unicornのエラーログと通常ログの位置を指定。
stderr_path File.expand_path('../../log/unicorn_stderr.log', __FILE__)
stdout_path File.expand_path('../../log/unicorn_stdout.log', __FILE__)
# Nginxで使用する場合は以下の設定を行う。
# listen File.expand_path('../../tmp/sockets/unicorn.sock', __FILE__)
# とりあえず起動して動作確認をしたい場合は以下の設定を行う。
listen 8080
# ※「backlog」や「tcp_nopush」の設定もあるけど、よくわかって無い。
# プロセスの停止などに必要なPIDファイルの保存先を指定。
pid File.expand_path('../../tmp/pids/unicorn.pid', __FILE__)
# 基本的には`true`を指定する。Unicornの再起動時にダウンタイムなしで再起動が行われる。
preload_app true
# 効果なしとの記事を見たので、コメントアウト。
# GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
# USR2シグナルを受けると古いプロセスを止める。
# 後述するが、記述しておくとNginxと連携する時に良いことがある。
before_fork do |server, worker|
defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, 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
起動する
とりあえず、ローカルで起動するなら上記のファイルを配置してRAILS_ROOT
で以下のコマンドを叩きます。
$ bundle exec unicorn_rails -c config/unicorn.rb
また、以下のコマンドでも起動します。
$ bundle exec unicorn -c config/unicorn.rb
unicorn
とunicorn_rails
の違いはRACK
で動かすかRAILS
で動かすかの違いです。
RAILS
はRACK
上で動いているため、どちらのコマンドでも起動します。
細かい点で挙動に違いがあります。
以下のURLが参考になると思います。
unicornとunicorn_railsのオプションの違い
動けば良いという方はunicorn_rails
を使いましょう。
また、-D
オプションをつければデーモン化されます。
-E
をつければRailsの環境オプションに合わせて起動します。(ここがunicorn
とunicorn_rails
で違う挙動をします。)
$ bundle exec unicorn_rails -c config/unicorn.rb -D -E $RAILS_ENV
ブラウザから以下のURLでアクセスできることが確認できると思います。
http://localhost:8080
Unicornの停止/再起動
こちらのサイト通りです。
以下、転記します。
停止コマンド
$ kill -QUIT `cat /path/to/unicorn.pid`
再起動コマンド
$ kill -HUP `cat /path/to/unicorn.pid`
緩やかな再起動コマンド
$ kill -USR2 `cat /path/to/unicorn.pid`
こちらの処理を行う際にbefore_fork
とpreload_app true
が役立ちます。
このコマンドを叩くと新プロセス
を立ち上げて旧プロセス
を停止します。
一時的に新旧両方のプロセスが立ち上がる事でダウンタイムをなしの状態を作り出せます。
before_fork
を記載してないと、旧プロセスがずっと残ってしまいます。
preload_app true
を記載しないと自分自身が再起動されます。(未確認)
CapistranoでUnicornを使う場合
別記事でまとめる予定だが、以下のgem
を使用すると簡単に使える。
gem 'capistrano3-unicorn'
上記をインストールして以下で使用する。
require 'capistrano3/unicorn'
中身を見ればわかるが、これは自分自身でも作る事ができる。
また、起動コマンドがunicorn
になってるので注意が必要である。
僕が犯したミス
僕はcapistrano3/unicorn
が何ものかわからなかったため、require 'capistrano3/unicorn'
とunicorn.rake
を両方書いてしまい、二重にunicorn
が立ち上がってしまうという恥ずかしいミスをしてしまった・・・。
しかも、中身を追わなかったため原因の解明にとても時間がかかった・・・。
(ちゃんと中身は見るべきですね。)
capからrakeへ
どうでも良い事だが、CapistranoのTaskが*.cap
から*.rake
に変わってた。
引っかかって、構築に時間がかかった・・・
(unicorn.cap
というファイルを作って、読み込まれないなぁ・・・って思ってた。)
Railsのログローテーションについて
こちらが参考になります。
Ruby on Rails - Unicorn のログローテーション!
最後に
僕は環境構築を一度したら、その後なかなか環境構築を行わない。
前の時はPassenger
をApache
に設定したらその設定を使いまわしてアプリケーションを作ってしまうため、環境周りが本当に苦手である。
なので、僕のためにもこの記事が必要だった。
この記事が僕のような環境開発が苦手な人の役に立てれば幸いである。
追記
Capistranoでunicornを使ったアプリをデプロイしているとBundler::GemfileNotFoundという例外があがることがある。
というかはまったので追加しました。
ENV['BUNDLE_GEMFILE'] = rails_root + "/Gemfile"