TechBox

スタートアップで働くRails&機械学習エンジニアのブログ。時々GT-Rと旅行。

NginxとUnicornでRubyonRailsの本番アプリサーバー構築手順

Railsに標準で入っているWEBrickは、開発中には気軽に動かせて便利で問題なしですが、
本番でRailsサーバーを動かすには、やっぱりきちんとWEBサーバーを構築してあげる必要があります。
そこで、Rails周りでは最近よく聞くNginx + Unicornでの構成を構築してみたいと思います。

https://nginx.org/nginx.png

軽い解説

Nginxとは

エンジンエックスと読みます。
いわゆるWEBサーバーで、Apacheと同様の役割を担っているんですが、最近良く聞くようになってきましたね。
Apacheよりも動作が速くなる事もあり、優秀ですね。
nginx

Unicornとは

そのままユニコーンと読みます。
Rack Webサーバーなんですが、そもそもRackとはRubyにてサーバーとアプリケーション・フレームワークの間の
インターフェイス的役割をするライブラリの事です。
UnicornはRackの機能もWebサーバーの機能も併せ持っていて、そういった意味ではWEBrickも同じ立ち位置です。
なので、UnicornとRailsの組み合わせでも動きます。
じゃあなぜこの組み合わせなのかという話なんですが、UnicornはWEBrickより優れているけど、
Webサーバー機能はNginxの方が優れている。
だったら最高の組み合わせが、Rails + Unicorn + Nginxなんじゃないかってなる感じですかね。

前提

今回構築した環境の条件例です。

  • Railsは稼働済みで、WEBrickでアプリケーションが動くレベルになっている事
  • CentOS7 64bit
  • Ruby 2.3.1
  • Rails 4.2.6
  • unicorn 5.1.0
  • nginx 1.10.1

手順

Unicornインストール

Gemfileに記載して、インストールするだけです。
以下、対象のプロジェクトで実行します。

project/Gemfile

gem 'unicorn'

shell

bundle install

を実行します。

 

Unicorn設定ファイル準備

project/config 配下にunicorn.rbファイルを新規で作成します。
用意したファイルに以下の様に記述します。

project/config/unicron.rb

# -*- coding: utf-8 -*-
worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
timeout 15

# ソケット
listen "/run/unicorn/unicorn.sock"
pid "/run/unicorn/unicorn.pid"

# ログ
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
     sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
     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
  • listenとpidは環境によって指定を変更して下さい。
    なお、Linuxの権限設定周りを確認する事も重要です。chmodなどで、適宜権限を与えて下さい。
  • ENV[‘RAILS_ROOT’]と書いているので、Linux側の環境変数で定義してあげて下さい。

Unicornの動作確認

Shellで実行していきます。

プロセス起動
shell

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

起動確認
shell

ps -ef | grep unicorn | grep -v grep

一端停止
shell

kill -9 [Process ID]

 

UnicornをRakeのTaskに埋め込む

毎回コマンドを打つのが大変なので、rakeコマンドを作ってあげます。 まずはTaskテンプレートを作成します。

shell

bundle exec rails generate task unicorn

作成されたTaskを以下内容に書き換えます。
lib/tasks/unicorn.rake

namespace :unicorn do
  desc "Start unicorn for production env."
  task(:start) do
    config_path = "#{Rails.root}/config/unicorn.rb"
    sh "unicorn_rails -c #{config_path} -E development -D"
  end

  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("/run/unicorn/unicorn.pid").to_i
    rescue Errno::ENOENT
      raise "Unicorn doesn't seem to be running"
    end
  end
end

pidの場所などは設定ファイルと合わせます。
これで以下コマンドにてUnicornの起動、停止が可能となります。
shell

bundle exec rake unicorn:start
bundle exec rake unicorn:stop

 

Nginxのインストール

続いてNginxをインストールしていきます。

リポジトリからインストール

まずはリポジトリをインストールします。

shell

http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

続いて、Nginxのパッケージをインストールします。
shell

sudo yum install --enablerepo=nginx nginx

 

動作確認

# 起動
systemctl start nginx
# 停止
systemctl stop nginx
# 自動起動設定(必要であれば)
systemctl enable nginx
# 設定適用
systemctl reload nginx
# ステータス確認
systemctl status nginx

 

Nginx設定ファイル準備

デフォルトのファイルを一端待避し、設定ファイルを準備します。

shell

cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/projectname.conf
mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bk

用意したconfファイルを書き換えます。
shell

vi /etc/nginx/conf.d/projectname.conf

/etc/nginx/conf.d/projectname.conf

upstream unicorn {
    server unix:/run/unicorn/unicorn.sock;
}

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;
    error_log   /var/log/nginx/host.error.log;

    root  /mnt/hgfs/source/projectname;
    try_files $uri.html $uri/index.html $uri @unicorn;

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /500.html;
    error_page 404 /404.html;

  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を再起動します。 www.techbox.jp

www.techbox.jp

www.techbox.jp

動作確認

UnicornとNginxを起動させ、「http://< IPAddress > or < HostName >/」にアクセスし、
アプリが起動していれば成功です。

www.techbox.jp

www.techbox.jp

www.techbox.jp