7839

雑草魂エンジニアブログ

【Puma】Rails 5.2 + Puma + Nginx のデプロイ設定

先日、【EC2】Rails5 環境構築(Ruby + MySQL5.7 + Node.js + Nginx) について書いた。そして、今回は、アプリケーションサーバーである Puma について色々と調べて設定したので、備忘録を残しておく。(以前、Rails を使っていた時は、Unicorn が主流だったのに、Rails5 からは標準サーバーも Puma に変わったこともあり、今回は Puma を採用してみた。)

Pumaとは

github.com

Puma is a simple, fast, multi-threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications.

Puma は、シンプル、高速、マルチスレッドで多数の並列処理を実現できる Ruby/Rack アプリケーションの HTTP 1.1 サーバーである。

ここで、「マルチスレッド」、「Ruby/Rack アプリケーション」という言葉に注目してみる。

マルチスレッド

Puma はマルチスレッドで動いていることが大きな特徴である。対照的に、Unicornマルチプロセスで動いている。CPU は一度に1つのプロセスしか実行できず、マルチプロセスの場合、CPU のコア数に応じて並列処理できる数に制限がある。しかしながら、マルチスレッドの場合は、1つのプロセスに複数のスレッドが存在し、並行して処理を行うため、CPU のリソースが少ない中でも効率的に処理を行うことができる。

Ruby/Rack アプリケーション

Rack とは、Rubyにおけるサーバとアプリケーション/フレームワーク間のインターフェースの役割を果たすライブラリである。PythonWSGI に影響されて開発されたらしく、WebサーバとWebアプリケーション/フレームワーク間の標準インターフェースを定める「仕様」である。

rails serverコマンドは、Rack::Serverのオブジェクトを作成し、Webサーバーを起動している。

Railsガイド 参照

簡単な概略図はこのような形になる。

f:id:serip39:20201224001935p:plain

HTTP リクエストを web サーバーである Nginx や Apache で受け取り、Nginx はそのリクエストを Puma に Socket 通信で渡し、Puma はそのリクエストを Rack::Server に渡し、最終的に Rails の router に渡される。

インストールに関して

Rails5 以上であれば、標準Webサーバーなので、最初に生成された Gemfile に含まれているので、新規にインストールをする必要はないが、インストールする場合は、以下の通りである。

$ gem install puma
$ puma

Rails で開発をする場合に、rails server をすることで、Puma が起動している。

$ rails server

Puma starting in single mode...
* Version 3.9.1 (ruby 2.4.0-p0), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: production
* Listening on tcp://0.0.0.0:3000 
Use Ctrl-C to stop

設定に関して

Puma は、Railsの場合、config/puma.rb で詳細な設定をすることができる。もちろん、オプションコマンドで設定も可能であるが、毎回コマンドを打つのが面倒なので、設定ファイルに用いる。

開発時は、Default の設定で問題ないので以下の通りである。

# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
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 `pidfile` that Puma will use.
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }

# Specifies the number of `workers` to boot in clustered mode.
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }

# Use the `preload_app!` method when specifying a `workers` number.
# preload_app!

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

本番環境では、Nginx をリバースプロキシとして Puma の前段におき、UNIXドメインソケットを経由して Nginx とPuma が通信を行う。

Puma 側では、Pumaを起動した時に、「puma.sock」を生成するようにする。

#port        ENV.fetch("PORT") { 3000 }
#portの設置の部分はコメントアウトしておく。そうでないと、puma.sockを参照しないことがある模様。
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"

Nginx 側では、/etc/nginx/conf.d/ に新規に設定ファイルを作成する。

upstream app_server {
  # for UNIX domain socket setups
  # 上記で設定したpuma.sockファイルの絶対パスを指定する
  server unix:///app/sample-app/tmp/sockets/puma.sock;
}
server {
  #ポート80番を許可する
  listen 80;
  #ホスト名を指定する
  server_name _;
  #静的ファイルのパスをドキュメントルートに設定する
  root /app/sample-app/public;
  # ドキュメントルート配下を以下の順番で検索する
  try_files $uri/index.html $uri.html $uri @app;
  # @appの場合は、以下の設定を読み込ませる
  location @app {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server; #upstreamで指定した名前で設定する
  }
  # エラーページの参照先を設定する
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /app/sample-app/public;
  }
}

Nginx の設定ファイルの修正が完了したら、設定に問題がないか確認を行う(successful が表示されれば、OK.)

$ sudo nginx -t
nginx: [warn] conflicting server name "_" on 0.0.0.0:80, ignored
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Nginxの設定を書き換えたので、再起動する

$ sudo systemctl reload nginx

Pumaを起動する(どのコマンドでも起動することができる)

$ bundle exec rails s
$ bundle exec puma
$ bundle exec pumactl start

これで設定は完了である。 http://<---IP address->:80 にアクセスすると、Railsアプリケーションが表示される。

コマンドに関して

Puma には、上記でも示したように、3つの制御方法が存在する。(個人的には、pumactl が使いやすいと思っている。)

  • rails sの場合
  • pumaコマンドの場合
  • pumactlの場合

rails sの場合

Railsアプリケーションの起動と同時に、Pumaも起動する

$ bundle exec rails s -e production

Puma ではデフォルトの設定ファイル config/puma.rb 以外にも、実行環境に応じたconfig/puma/[実行環境].rb という設定ファイルを参照させることができる。

-e productionの場合、config/puma/production.rb 参照する。(なかった場合は、デフォルトを参照する。)

停止する場合は、以下のように Puma のプロセスを確認して、kill する

# process IDの確認をする
$ ps aux | grep puma
# プロセスを停止させる
$ kill -9 <--process ID-->

pumaコマンドの場合

設定ファイルを指定して、起動する(-Cのオプションがない場合は、デフォルトを参照するが、設定することをオススメする)

$ bundle exec puma -C config/puma.rb

停止する場合は、rails s 同様に、プロセスを確認して、kill する

pumactlの場合

pumactl を使う場合は、オプションコマンドなどで設定をすることができないので、config/puma.rb にきちんと設定を書いておく必要がある。

# 起動する
$ bundle exec pumactl start
# 状態を確認する
$ bundle exec pumactl status
# 停止する
$ bundle exec pumactl stop
# 再起動する
$ bundle exec pumactl restart

まとめ

今回は、アプリケーションサーバーである Puma についてまとめを行った。

それでは、ステキな開発ライフを。

関連記事

serip39.hatenablog.com

serip39.hatenablog.com