Rails
nginx
unicorn

Rails 4.2 + Unicorn + Nginx でアプリケーションサーバの構築

More than 3 years have passed since last update.


Unicorn とは

Rails 標準アプリケーションサーバは重いので、動作が軽い Unicorn を導入してみる。


環境構築

Chef-Solo + Berkshelf で Rails 4 の開発環境を構築 を参考に。

他のサーバとは別のプライベートIPを割り当てておく。


プロジェクト作成

以下のコマンドを実行していく。

$ mkdir ~/projects/unicorn_sample

$ cd ~/projects/unicorn_sample
$ bundle init

作成されたGemfileを以下のように書き換える。


Gemfile

source 'https://rubygems.org'

gem 'rails', '4.2.0'


以下のコマンドを実行。

$ bundle install --path vendor/bundle

$ bundle exec rails new .
...
Overwrite /home/vagrant/projects/unicorn_sample/Gemfile? (enter "h" for help) [Ynaqdh] Y
...

Gemfile を下記のように書き換える。


Gemfile

source 'https://rubygems.org'

gem 'rails', '4.2.0'
gem 'sqlite3'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'therubyracer', platforms: :ruby
gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc
gem 'bcrypt', '~> 3.1.7'
gem 'unicorn'

group :development, :test do
gem 'byebug'
gem 'web-console', '~> 2.0'
gem 'spring'
end


下記コマンドを実行。

$ bundle install --path vendor/bundle


テスト用アプリ作成

$ bundle exec rails generate scaffold board title:string text:string

$ rake db:migrate

config/routes.rb を下記のように編集


config/routes.rb

Rails.application.routes.draw do

resources :boards
root boards#index"
end

下記コマンドでサーバーを起動し、ページが見えるかどうか確認しておく。

$ bundle exec rails server -b 0.0.0.0


Unicorn の設定

config/unicorn.rb を下記の内容で新規に作成 (参考資料)。


config/unicorn.rb

# -*- coding: utf-8 -*-

worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15
preload_app true # 更新時ダウンタイム無し

listen "/tmp/unicorn.sock"
pid "/tmp/unicorn.pid"

before_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
Process.kill 'QUIT', Process.pid
end

defined?(ActiveRecord::Base) and
ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
Signal.trap 'TERM' do
puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
end

defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
end

# ログの出力
stderr_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])
stdout_path File.expand_path('log/unicorn.log', ENV['RAILS_ROOT'])


下記コマンドで unicorn 起動。

$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D

起動できているかどうかは下記コマンドで確認できる。

$ ps -ef | grep unicorn | grep -v grep

Unicorn を止めるには下記のコマンドでプロセスをKillする。

$ kill -9 [Process ID]

このままだと起動 & 終了が面倒なので、Rakeのtask に Unicorn の起動 & 終了の設定を記述する。

このページを参考にした。

Taskのテンプレートファイルを作成する。



$ bundle exec rails generate task unicorn

以下の内容に変更する。


lib/tasks/unicorn.rake

namespace :unicorn do

##
# Tasks
##
desc "Start unicorn for development env."
task(:start) {
config = Rails.root.join('config', 'unicorn.rb')
sh "bundle exec unicorn_rails -c #{config} -E development -D"
}

desc "Stop unicorn"
task(:stop) { unicorn_signal :QUIT }

desc "Restart unicorn with USR2"
task(:restart) { unicorn_signal :USR2 }

desc "Increment number of worker processes"
task(:increment) { unicorn_signal :TTIN }

desc "Decrement number of worker processes"
task(:decrement) { unicorn_signal :TTOU }

desc "Unicorn pstree (depends on pstree command)"
task(:pstree) do
sh "pstree '#{unicorn_pid}'"
end

def unicorn_signal signal
Process.kill signal, unicorn_pid
end

def unicorn_pid
begin
File.read("/tmp/unicorn.pid").to_i
rescue Errno::ENOENT
raise "Unicorn doesn't seem to be running"
end
end

end


下記のコマンドでUnicornを起動、停止出来るようになる。

$ bundle exec rake unicorn:start

$ bundle exec rake unicorn:stop

とりあえず、Unicornを起動しておく。


Nginx の設定

下記コマンドで設定ファイルの作成を行う。

$ sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/local.conf

$ sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bk

/etc/nginx/conf.d/local.conf を下記のように書き換える。

upstream の server の部分は Unicorn 側で指定した sock ファルの場所を、

root の部分はアプリケーションのルートディレクトリを指定する。


/etc/nginx/conf.d/local.conf

upstream unicorn {

server unix:/home/vagrant/projects/unicorn_sample/tmp/unicorn.sock;
}

server {
listen 80 default_server;
server_name サーバ名;

access_log /var/log/nginx/sample_access.log;
error_log /var/log/nginx/sample_error.log;

root /home/vagrant/projects/unicorn_sample;

client_max_body_size 100m;
error_page 404 /404.html;
error_page 500 502 503 504 /500.html;
try_files $uri/index.html $uri @unicorn;

location @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://unicorn;
}
}


Nginx を(再)起動する。

$ sudo service nginx restart


動作確認

http://[ドメイン名]/ にアクセスして、

$ bundle exec rails server -b 0.0.0.0

で起動した場合と同じ画面が表示されていればOK。

D3A692FF-37E8-4124-9F3B-A2A3D87B4ADD.png