可能性の獣
mongrelで動かしていたRailsアプリをUnicornに切り替えた。 nginxの方が情報は多いんだけど、今回は他のWebアプリも動いてるので敢えてApacheにする。 若干ハマったのでメモ。
まず、Unicornのインストール。 ついでにRailsもアップデートしておく。 予めenvironment.rbのRAILS_GEM_VERSIONを変更しておき、
gem install unicorn
gem install -v 2.3.10 rails
cd /path/to/rails_app
rake rails:update
で完了。
次にunicornの設定。 設定ファイル名は任意だが、RAILS_ROOT/config/unicorn.conf.rbとする。 例ではポート5001、ユーザ名unicornで子プロセスは5つ立ち上げている。
user 'unicorn'
group 'unicorn'
shared_path = "/path/to/rails_app/shared"
pid "#{shared_path}/pids/unicorn.pid"
stderr_path "#{shared_path}/log/unicorn.stderr.log"
stdout_path "#{shared_path}/log/unicorn.stdout.log"
processes = 5
timeout = 75
listen = 5001
rails_env = ENV['RAILS_ENV'] || 'production'
worker_processes (rails_env == 'production' ? processes : 1)
preload_app true
timeout timeout
listen listen, :backlog => 2048
after_fork do |server, worker|
ActiveRecord::Base.establish_connection
begin
uid, gid = Process.euid, Process.egid
target_uid = Etc.getpwnam(user).uid
target_gid = Etc.getgrnam(group).gid
worker.tmp.chown(target_uid, target_gid)
if uid != target_uid || gid != target_gid
Process.initgroups(user, target_gid)
Process::GID.change_privilege(target_gid)
Process::UID.change_privilege(target_uid)
end
rescue => e
if RAILS_ENV == 'development'
STDERR.puts "couldn't change user"
else
raise e
end
end
end
ここでいったんテストしようとして、unicorn -C /path/to/rails_app/config/unicorn.conf.rb -E productionとかやると、config.ruが無いよとか言われる。無理矢理gemに含まれてるやつを持ってきて起動すると、今度は-E付けてるのになぜかdevelopment環境になったりしてわけわかめ。 正解は、unicornではなくunicorn_railsを使う。 これを踏まえて、deploy.rbはこんな感じに。
set :application, "app_name"
set :scm, :git
set :repository, "~/src/app_name"
set :branch, 'master'
set :deploy_via, :copy
set :deploy_to, "/path/to/#{application}"
set :user, "unicorn"
set :runner, "unicorn"
set :use_sudo, false
role :app, "app.example.com"
role :web, "www.example.com"
role :db, "db.example.com", :primary => true
set :rails_env, :production
set :unicorn_binary, "/usr/local/bin/unicorn_rails"
set :unicorn_config, "#{current_path}/config/unicorn.conf.rb"
set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid"
namespace :deploy do
task :start, :roles => :app, :except => { :no_release => true } do
run "cd #{current_path} && #{unicorn_binary} -c #{unicorn_config} -E #{rails_env} -D"
end
task :stop, :roles => :app, :except => { :no_release => true } do
run "kill `cat #{unicorn_pid}`"
end
task :graceful_stop, :roles => :app, :except => { :no_release => true } do
run "kill -s QUIT `cat #{unicorn_pid}`"
end
task :reload, :roles => :app, :except => { :no_release => true } do
run "kill -s USR2 `cat #{unicorn_pid}`"
end
task :restart, :roles => :app, :except => { :no_release => true } do
stop
start
end
end
sudo使う場合はtaskに#{try_sudo}とか入れる。 ちなみに一度目はエラーになっちゃうのでdeploy:coldを使うこと。 設定変えた時とかはdeploy:reloadを使えば無停止で切り替えられる。 ついでにapacheの設定。 mongrel_clusterだとapacheのロードバランサを使ったけど、unicornはそれ自体がロードバランサになるので全部masterに振り向ければいい。
ProxyRequests Off
<Proxy *>
Order deny,allow Allow from all
</Proxy>
ProxyPass / http://localhost:5001/
ProxyPassReverse / http://localhost:5001/
こんだけ。
色々分かってなくて手探りだったので、もうちょっと最適化できると思う。 特にunicorn.conf.rbは無駄が多い気がする…