BLOG

ブログ

2020年7月13日

1台のサーバに複数のRailsアプリを共存させる方法

オプスインでWebシステムを開発する際によく利用する言語とフレームワークはRyby on Railsなのですが、STG環境や本番環境ではリバースプロキシとしてnginxを使用しています。

 

1.はじめに

Railsアプリの開発では、動作確認を行う際にはRailsに同梱されているpumaサーバを用いることがほとんどです。

pumaはデフォルトだとポート番号3000で起動しますので、コマンド「rails s」で動作確認する時は http://localhost:3000/ にアクセスします。

 

一方でhttpのデフォルトポート番号は80なので、本番環境はもちろんSTG環境でもポート番号80でアクセスを受け付けるようにするのが一般的と思います。

 

pumaでも設定ファイル「{Rails_App}/config/puma.rb」に記載されているデフォルト値の3000から80に変更するか、もしくはコマンドでポート番号を指定して起動することでポート番号80で受け付けることができます。

【puma.rbの記述】
port        ENV.fetch("PORT") { 3000 }
【ポート番号を指定したpumaの起動コマンド例】

$ bundle exec puma -p 80

ですが、この方法ですと1台のサーバにつき1つのRailsアプリしかポート番号80を使うことができません。
そこでポート番号80の受付はnginxに任せ、サーバ内ではunixドメインソケット通信を用いることで、1台のサーバで複数のRailsアプリを動作させることができます。

具体的な設定例は以下の通りです。

2.nginxの設定

nginxはメインの設定ファイル(/etc/nginx/nginx.conf等)に記載するincludeにより複数のサーバ設定を行うことができます。

【nginx.conf】
前略
~
http {

~中略~
    include /etc/nginx/conf.d/*.conf;
~
後略

上記の設定例では、例えば「/etc/nginx/conf.d/sample_app_1.conf」のように「/etc/nginx/conf.d/」ディレクトリ配下に拡張子.confの設定ファイルを配置することで複数の設定ファイルが読み込まれます。

ですから、次のように各Railsアプリごとに設定ファイルを配置することで、nginxはポート番号80で2つ以上のRailsアプリにWebリクエストを振り分けることが可能になります。
ここでリクエストの振り分けは「server_name」を利用していますので、アクセスするURLは個別にドメインを設定する必要があります。(サブドメインの区別で可)

【sample_app_1.conf】
upstream app1 {
     server unix:///var/www/sample_app_1/tmp/sockets/puma.sock fail_timeout=0;
}

server {
    server_name sample_app_1.test.com;

    root /var/www/sample_app_1/public;

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

    real_ip_header     X-Forwarded-For;

    location @app1 {
        proxy_pass http://app1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
    }
    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}
【sample_app_2.conf】
upstream app2 {
     server unix:///var/www/sample_app_2/tmp/sockets/puma.sock fail_timeout=0;
}

server {
    server_name sample_app_2.test.com;

    root /var/www/sample_app_2/public;

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

    real_ip_header     X-Forwarded-For;

    location @app2 {
        proxy_pass http://app2;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
    }
    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

3.Rails(puma)の設定

pumaも設定ファイル「{Rails_App}/config/puma.rb」にunixドメインソケット通信を行うように記述しますが、開発環境でnginxを使用しない場合も想定して、環境変数を用いて環境別にリクエストの受付方法を切り替えるように設定します。

【puma.rb】
前略
~
# デフォルトのポート指定はコメントアウトする
#port        ENV.fetch("PORT") { 3000 }

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

# Rails6ではdevelopment環境以外ではドメイン名を指定する必要があるので、その環境変数を使用する
domain_name = ENV.fetch("DOMAIN_NAME") { "localhost" }
if domain_name != "localhost"
  app_dir = File.expand_path("../..", __FILE__)
  bind "unix://#{app_dir}/tmp/sockets/puma.sock"
  stdout_redirect "log/puma.stdout.log", "log/puma.stderr.log", true
  daemonize true
else
  # 開発環境(localhost)用にポート番号を指定
  port        ENV.fetch("PORT") { 3000 }
end
~
後略

puma.rbは各Railsアプリごとに設定する必要がありますが、設定内容は同一です。

このように設定することで、利用者からのWebリクエストはnginxがポート番号80で受け付け、「server_name」に設定しているドメイン名によってRailsアプリへのリクエストを振り分けすることが可能になります。

4.おわりに

本記事では複数のRailsアプリを1サーバに共存するための設定として紹介しましたが、開発環境ではpuma、STG/本番環境ではnginxを使用するケースでもpuma.rbの設定は参考になるかと思います。

コメントを投稿できません。