Vagrant & VirtualBox上のUbuntuでRuby + Rails5 + Puma + Nginx

  • 17
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

Rails5からデフォルトRackサーバがPumaになり、Unicornの代わりに利用される機会が増えそうなので、環境構築手順を自分用メモとして書いておきます。

投稿時のバージョン

  • Ubuntu 15.10
  • Ruby 2.3.0(rbenvでインストール)
  • Rails 5.0.0beta3
  • Puma 3.4.0
  • Nginx 1.9.3

ヘルパコマンドを用意

Pumaの推奨はJRubyかRubiniusですが、Rubyでもクラスターモードで実行させればそこそこパフォーマンスが出せるはずなので1、起動時にworkersにCPUコア数を指定します。

workersへの指定は起動引数-wでも可能ですので、CPUコア数を取得するヘルパコマンドを用意し、workersにCPUコア数が自動設定されるようにします2

$ mkdir -p ~/bin
$ echo 'cat /proc/cpuinfo | grep processor | wc -l' > ~/bin/ncpu; chmod +x ~/bin/ncpu
$ echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

動作確認

$ ncpu
4

Rails5プロジェクトを用意

プロジェクト作成

$ rails -v
Rails 5.0.0.beta3
$ rails new hello_rails5
$ cd hello_rails5
$ rails g scaffold person name age:integer
$ rails db:migrate
$ rails db:migrate RAILS_ENV=production

デフォルトDBはSQLite3になりますが、今回はそのままにします。

Pumaの設定

デフォルトで作成される設定ファイルへ、Nginx用の設定を追加します。

config/puma.rb
_proj_path = "#{File.expand_path("../..", __FILE__)}"
_proj_name = File.basename(_proj_path)
_home = ENV.fetch("HOME") { "/home/vagrant" }

pidfile "#{_home}/run/#{_proj_name}.pid"
bind "unix://#{_home}/run/#{_proj_name}.sock"
directory _proj_path

# --- ここまで追加 ---

# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum, this matches the default thread size of Active Record.
#
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count

# Specifies the `port` that Puma will listen on to receive requests, default is 3000.
#
port        ENV.fetch("PORT") { 3000 }

# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked webserver processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory. If you use this option
# you need to make sure to reconnect any threads in the `on_worker_boot`
# block.
#
# preload_app!

# The code in the `on_worker_boot` will be called if you are using
# clustered mode by specifying a number of `workers`. After each worker
# process is booted this block will be run, if you are using `preload_app!`
# option you will want to use this block to reconnect to any threads
# or connections that may have been created at application boot, Ruby
# cannot share connections between processes.
#
# on_worker_boot do
#   ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
# end

# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

Nginxの設定

/etc/nginx/conf.d/hello_rails5.conf
upstream hello_rails5 {
    # Path to Puma SOCK file, as defined previously
    server unix:/home/vagrant/run/hello_rails5.sock fail_timeout=0;
}

server {
    listen 80;
    server_name 192.168.33.10; # Vagrantfileに書かれているデフォルトIP

    root /path/to/hello_rails5/public; # /path/toを変更

    try_files $uri/index.html $uri @hello_rails5;

    location / {
        proxy_pass http://hello_rails5;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

設定追加後、Nginxを再起動

$ sudo service nginx restart

最小の設定で済むように、conf.dに今回のRailsアプリ用のバーチャルサーバ設定を追加します、初期インストールのファイルは触りません。

Rails5アプリを起動

development環境の場合は

$ puma -w $(ncpu)

production環境の場合は

$ rails assets:precompile RAILS_ENV=production 
# ※RAILS_ENV=productionはpumaの前
$ SECRET_KEY_BASE=$(rake secret) RAILS_SERVE_STATIC_FILES=true RAILS_ENV=production puma -w $(ncpu)

コマンドを叩くのが面倒な時は、起動用のaliasを用意して

$ echo "alias devpuma='puma -w \$(ncpu)'" >> ~/.bash_profile
$ echo "alias prodpuma='rails assets:precompile RAILS_ENV=production; SECRET_KEY_BASE=\$(rake secret) RAILS_SERVE_STATIC_FILES=true RAILS_ENV=production puma -w \$(ncpu)'" >> ~/.bash_profile
$ source ~/.bash_profile

aliasから起動

# developmentで起動
$ devpuma
# productionで起動
$ prodpuma

あとはブラウザからURLへアクセスして表示されれば環境構築は成功。

参考


  1. Apache Benchで何もしないControllerのURLを指定した場合、Unicornとほぼ同等のスコアが出ました、詳細な検証ではないので正確性に欠けると思います。 

  2. 後述で使用