環境
- CentOS Linux release 7.1.1503
- Ruby on Rails 5.0.0.1
- unicorn_rails v5.1.0
- nginx/1.10.1
nginxのインストール
CentOS6
$ sudo rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
$ sudo yum install -y nginx
CentOS7
$ sudo yum install http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
$ sudo yum install --enablerepo=nginx nginx
設定ファイル編集
{appname}の部分は任意。
/etc/nginx/conf.d/{appname}.conf
下記は最低限の設定。これだけでとりあえずrailsは動く。
/etc/nginx/conf.d/{appname}.conf
upstream rails-unicorn {
# nginxのソケット保存先指定
server unix:/home/vagrant/{appname}/tmp/sockets;
}
server {
# port
listen 80;
# サーバーのIPアドレス
server_name 192.168.33.10;
# DocumentRoot
root /home/vagrant/{appname}/public;
try_files $uri $uri.html $uri/index.html @rails-unicorn;
# charset
charset utf8;
# logs
access_log /var/log/nginx/{appname}/{appname}.access.log main;
error_log /var/log/nginx/{appname}/{appname}.error.log error;
location @rails-unicorn {
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://rails-unicorn;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
nginxの実行ユーザー変更
実行ユーザーをnginxからvagrantに変更
/etc/nginx/nginx.conf
/etc/nginx/nginx.conf
user vagrant;
(*snip*)
nginx起動
# 自動起動有効
$ sudo systemctl enable nginx
# 起動
$ sudo systemctl start nginx
unicronのインストール
Gemfileに下記追記
Gemfile
gem 'unicorn'
bundle install
$ bundle install --path vendor/bundle
configの下にunicorn.rbというファイルを作成する。
引用元:Unicorn設定のまとめ
config/unicorn.rb
# 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
#Unicornは、リクエストを振り分ける一つのmasterプロセスと、実際にリクエストを処理する複数のworkerプロセスで構成されるアーキテクチャになっている。
#worker_processesはworkerプロセスの数を指定する。
#実際のアプリのメモリ使用量などを見ながらworker数を調節できるように、環境変数を指定できるようにしてあるとのこと。
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
unicorn起動
$ bundle exec unicorn_rails -c config/unicorn.rb -D -E development
unicorn起動スクリプト例
lib/tasks/unicorn.rake
namespace :unicorn_rails do
RAILS_ENV=ENV['RAILS_ENV']
UNICORN_CMD='unicorn_rails'
UNICORN_CONFIG=%Q(#{File.dirname(File.expand_path(__FILE__))}/../../config/unicorn/#{ENV['RAILS_ENV']}.rb)
UNICORN_PID=%Q(#{File.dirname(File.expand_path(__FILE__))}/../../tmp/pids/unicorn.pid)
task :environment do
end
desc 'unicorn_rails start'
task :start => :environment do
sh %Q(/bin/bash -lc "bundle exec #{UNICORN_CMD} -c #{UNICORN_CONFIG} -E #{RAILS_ENV} -D")
end
desc 'unicorn_rails stop'
task :stop => :environment do
if %x(ps ho pid p `cat #{UNICORN_PID}`).present?
sh %Q(kill `cat #{UNICORN_PID}`)
end
end
desc 'unicorn_rails graceful_stop'
task :graceful_stop => :environment do
if %x(ps ho pid p `cat #{UNICORN_PID}`).present?
sh %Q(kill -s QUIT `cat #{UNICORN_PID}`)
end
end
desc 'unicorn_rails reload'
task :reload => :environment do
if %x(ps ho pid p `cat #{UNICORN_PID}`).present?
sh %Q(kill -s USR2 `cat #{UNICORN_PID}`)
else
Rake::Task['unicorn_rails:start'].execute
end
end
desc 'unicorn_rails restart'
task :restart => :environment do
if %x(ps ho pid p `cat #{UNICORN_PID}`).present?
Rake::Task['unicorn_rails:stop'].execute
else
puts %Q(unicorn didn't work.)
end
Rake::Task['unicorn_rails:start'].execute
end
end
capistrano task用
lib/capistrano/tasks/unicorn.rake
namespace :unicorn_rails do
task :environment do
set :unicorn_cmd, 'unicorn_rails'
set :unicorn_config, "#{current_path}/config/unicorn/production.rb"
set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid"
end
desc 'unicorn_rails start'
task :start => :environment do
on roles(:app), reject: lambda { |h| h.properties.no_release } do
execute "cd #{current_path} && bundle exec #{fetch(:unicorn_cmd)} -c #{fetch(:unicorn_config)} -E #{fetch(:rails_env)} -D"
end
end
task :stop => :environment do
on roles(:app), reject: lambda { |h| h.properties.no_release } do
if test("[ -f #{fetch(:unicorn_pid)} ]")
execute "kill `cat #{fetch(:unicorn_pid)}`"
end
end
end
task :graceful_stop => :environment do
on roles(:app), reject: lambda { |h| h.properties.no_release } do
if test("[ -f #{fetch(:unicorn_pid)} ]")
execute "kill -s QUIT `cat #{fetch(:unicorn_pid)}`"
end
end
end
task :reload => :environment do
on roles(:app), reject: lambda { |h| h.properties.no_release } do
if test("[ -f #{fetch(:unicorn_pid)} ]")
execute "kill -s USR2 `cat #{fetch(:unicorn_pid)}`"
else
Rake::Task['unicorn_rails:start'].execute
end
end
end
task :restart => :environment do
on roles(:app), reject: lambda { |h| h.properties.no_release } do
Rake::Task['unicorn_rails:stop'].execute
Rake::Task['unicorn_rails:start'].execute
end
end
end
unicorn自動起動設定
起動スクリプトの作成
/etc/init.d/unicorn
#!/bin/bash
#chkconfig:2345 85 70
#description:unicorn shell
USER='rails_user'
RAILS_ROOT='/path/to/rails_app/current'
NAME='unicorn_rails'
PID="${RAILS_ROOT}/tmp/pids/unicorn.pid"
start()
{
if [ -e $PID ]; then
PID_NUM=`cat ${PID}`
PROCESS=`ps ho pid p ${PID_NUM} > /dev/null; echo $?`
if [ "${PROCESS}" != 0 ]; then
echo 'rm ghost pid'
rm -f ${PID}
else
echo "$NAME already started"
exit 1
fi
fi
echo "start $NAME"
su - $USER -lc "cd ${RAILS_ROOT} && bundle exec rake unicorn_rails:start"
}
stop()
{
if [ ! -e $PID ]; then
echo "$NAME not started"
exit 1
fi
echo "stop $NAME"
su - $USER -lc "cd ${RAILS_ROOT} && bundle exec rake unicorn_rails:stop"
}
force_stop()
{
if [ ! -e $PID ]; then
echo "$NAME not started"
exit 1
fi
echo "stop $NAME"
kill -INT `cat ${PID}`
}
reload()
{
if [ ! -e $PID ]; then
echo "$NAME not started"
start
exit 0
fi
echo "reload $NAME"
#kill -HUP `cat ${PID}`
su - $USER -lc "cd ${RAILS_ROOT} && bundle exec rake unicorn_rails:reload"
}
restart()
{
stop
sleep 3
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
force-stop)
force_stop
;;
reload)
reload
;;
restart)
restart
;;
*)
echo "Syntax Error: release [start|stop|force-stop|reload|restart]"
;;
esac
$ sudo chkconfig --add unicorn
$ sudo chkconfig on
$ sudo chkconfig --list