Ruby on Railsでアプリ作ったけど、本番環境への公開ってどうすればいいんだろう?
こんな悩みを解決します。
私は現在React + Ruby on RailsでWebアプリを開発しています。
フロントは全てReactで作り、Ruby on RailsはAPIモードで作ってます。
そして、ある程度形になってきたので、実際にサーバ上に公開してみて動作確認をしようとしたのですが、めちゃくちゃ苦労しました。
正直、開発よりもこっちの方が大変でした・・・
出てくる情報のほとんどがDockerを使ったもの、それ以外はUnicornを組み合わせた複雑なものばかりです。
ローカルでDockerコンテナ内で開発していないのに、わざわざDockerコンテナ作るのも嫌だったのと、Dockerコンテナ上でサービス動かして、それを本番運用するのはちょっと怖かったためDockerを使った方法はダメ。
Ruby on Rails初心者の私には、Unicornは使い方がよくわからず試してみたもののうまく動かず断念。
Nginxだけを使ったシンプルな構成の情報が全くない・・・
絶望しながら、出てくる情報を組み合わせて試行錯誤しながら動かしているうちに、ようやくまともに動くようになりました!
そのため、私と同じようにNginxとPumaだけ使ったシンプルな構成で本番環境を構築したい人向けにこの記事を書くことにしました。
サーバに公開するための手順
実際サーバへと公開するための手順はざっくり以下の通り。
- VPSを契約する
- ReactやRuby on Railsなどの環境を構築する
- Nginxをインストールする
- Reactをビルドする
- NginxとPumaの設定をする
- SSL化(HTTPS化)する
本記事では、これら手順の中で全然情報がなかったNginxとPumaの設定をする部分をメインに解説していきます。
他の部分については、さらっとだけ触れていきます。
VPSを契約する
サーバとして使うため、今回はVPSを使うことにしました。
レンタルサーバでもできるかもしれませんが、できることにある程度制限がかかってしまうので、私はVPSを選択しました。
AWSや他のホスティングサービスを使うって選択肢もありますが、使いやすさと料金的なことを考えてもVPSが一番お手軽かなと。
ちなみに契約したのは、本ブログでも愛用しているConoHaVPS
ReactやRuby on Railsなどの環境構築をする
VPSを契約してサーバの準備ができたら環境構築をしましょう。
ちなみに、OSはUbuntu22.04を使用しています。
ReactやRuby on Railsの環境構築方法は調べたらいくらでも情報が出てくるので割愛。
ここはローカル環境構築とほとんど一緒なので、すでに開発に取り掛かってる人なら問題ないかと。
必要に応じてMySQLなどもインストールしておいてください。
Nginxをインストールする
Webサーバのインストールです。
Apacheでもいいのですが、最近はNginxを使っているところが多くなってきているらしく、流れに乗ってNginxにしました。
インストール自体は難しいことなく一瞬です。
設定については、後から詳しく解説します。
Reactをビルドする
Nginxの設定をする前に、Reactのビルドをしておいた方がいいです。
Nginxの設定でルートディレクトリを指定するのですが、そのときReactのビルド先ディレクトリを指定します。
そのため、ビルドしていないとそのディレクトリが見つからずエラーが出てしまうので、先にビルドしておきましょう。
NginxとPumaの設定をする
実際にWebサーバ(Nginx)とRuby on RailsのPumaを関連付ける設定を行います。
この設定を行うことで、Nginxが受けた通信をRailsへと流すことができるようになります。
簡単に言うと、普段開発時にrails sコマンドでRailsのサーバを立ち上げてますよね?
その際、http://localhost〜でアクセスしていたかと思いますが、この設定を行うことで、Nginxが公開しているURLにアクセスすると、rails sで立ち上げたRailsのサーバへとアクセスされるようになります。
具体的な設定方法については、後から詳しく解説します。
SSL化(HTTPS化)する
Webサービスを公開するのであれば、セキュリティのことも考えてSSL化(HTTPS化)することは必須と言っても過言ではありません。
方法も簡単。
- VPSのコントロールパネル上でSSLの設定をする
- サーバ上でcertbotをインストールする
- Nginxの設定をした後certbotコマンドを実行する
たったこれだけでSSL化が完了します。
ただし、NginxとPumaの設定を先に終えておく必要があるので、そこだけ気をつけてください。
Ruby on Railsを使うためのNginxの設定
前置きが長くなってしまいましたが、ここからが本題です。
Nginxの設定方法はいろいろありますが、私はsite-availableディレクトリに設定する方法を使っているので、その方法で解説していきます。
- Reactのディレクトリパス
→ /var/www/html/react - Ruby on Railsのディレクトリパス
→ /var/www/html/rails - 使用するドメイン
→ test.com
バーチャルホストの設定
site-availableディレクトリに、適当な名前のファイルを作ります。
ファイル名は、ドメイン名にするのが後からわかりやすいのでオススメです。
site-availableディレクトリ内には、defaultというベースとなるファイルがあるので、それを参考に最低限の設定を入れます。
server {
listen 80;
listen [::]:80;
server_name test.com; # ドメイン名を入れる
root /var/www/html/react/build; # Reactのビルド先
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
この設定だけでビルドしたReactが動くようになるはずです。
別のドメインでアプリを動かしたい場合は、また新しくtest2.comのようにファイルを作って、同じように設定を入れればOKです。
Pumaの設定
次にRailsのPumaの設定です。
ちなみに、私のRails環境は以下の通り。
Ruby 3.2.2
Ruby on Rails 7.0.7
まず、必要なパッケージをインストールします。
Gemfileに以下を追加してください。
gem "puma-daemon", require: false
古いバージョンのPumaだとデーモン化するための機能が一体化していたんですが、最近のはそれらが別々になっているため、別途インストールが必要なようです。
必要なパッケージのインストールが終わったら、次に設定をしていきます。
まずこちら元々入っているPumaの設定です。
コメントは全て消してあるので、かなりすっきりしているように感じるかもしれません。
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
port ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
plugin :tmp_restart
この設定を以下のように変更します。
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
rails_env = ENV.fetch('RAILS_ENV') { 'development' }
if rails_env == 'production'
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"
rails_root = Rails.root
state_path File.join(rails_root, 'tmp', 'pids', 'puma.state')
stdout_redirect(
File.join(rails_root, 'log', 'puma.log'),
File.join(rails_root, 'log', 'puma-error.log'),
true
)
require 'puma/daemon'
daemonize
else
port ENV.fetch("PORT") { 3000 }
end
environment rails_env
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
plugin :tmp_restart
いろんなサイトを参考にして作ったので、もしかすると不要な設定・足りてない設定があるかもしれませんが、一応これで見た目正常に動いてます。
変更点についてさらっと解説。
if rails_env == 'production'
bind "unix://#{Rails.root}/tmp/sockets/puma.sock"
本番環境(production)の場合はソケットをバインドします。
これによりNginxからPumaへと通信を流すことができるようになります。
require 'puma/daemon'
daemonize
先程インストールしたパッケージを使ってデーモン化してます。
これによりSSH接続が切れた後でもRailsのサーバが動き続けてくれます。
else
port ENV.fetch("PORT") { 3000 }
ポート設定は本番環境だとコメントアウトしましょう的な記事をよく見かけますが、if文で分岐させることにより自動で切り替わるようにしてます。
こうすることで、本番環境として立ち上げたときはNginxへとバインド、それ以外の環境の場合は今までと同じくlocalhsot:3000を使用することができます。
NginxとPumaを連携させる
これでPumaの設定もできたので、Nginxと連携させていきます。
先程作成したNginxの設定ファイルを以下のように修正します。
upstream api {
server unix:///var/www/html/rails/tmp/sockets/puma.sock;
}
server {
listen 80;
listen [::]:80;
server_name test.com; # ドメイン名を入れる
root /var/www/html/react/build; # Reactのビルド先
index index.html;
location / {
try_files $uri $uri/ =404;
}
location /api/v1 {
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://api;
}
}
この設定が今回一番苦労したポイントです。
ここにたどり着くまで、かなり苦労しました・・・
では、見ていきましょう。
upstream api {
server unix:///var/www/html/rails/tmp/sockets/puma.sock;
}
Pumaでバインドしたソケットを指定する設定です。
基本的にはRailsのプロジェクトのディレクトリを指定すればOKです。
server unix://<Railsのディレクトリのパス>/tmp/sockets/puma.sock;
locationで接続先を振り分けています。
今回APIとして動作するRailsの通信は、全てtest.com/api/v1/◯◯となっています。
そのため、”/api/v1”に該当する通信には、location /api/v1 {}の中の処理適用されます。
ポイントは以下の部分。
proxy_pass http://api;
このhttp://apiとはなんでしょうか?
答えは、先程設定したPumaのソケットを指定する部分です。
upstream api {
server unix:///var/www/html/rails/tmp/sockets/puma.sock;
}
この”api”の部分が該当します。
つまり、/api/v1の通信が来たら、RailsのPumaへと流すことになるんです。
逆に、該当しない通信は全てReactへと通されます。
これでNginxとRailsのPumaを連携させる設定が完了しました。
設定を反映させるため、Nginxの再起動を忘れないようにしましょう。
systemctl restart nginx
certbot -d test.com
RailsのPumaをバックグランドで動かす
NginxとPumaの設定が完了しましたが、このままではまだAPIとして動作することはできません。
Pumaが起動していないからです。
そのため、Pumaをサーバとして動かしましょう。
コマンドは以下の通り。
rails s -e production
開発環境で頻繁に使うrails sコマンドを、production環境にて実行するコマンドとなります。
このコマンドを実行することにより、Pumaの設定に入れたif rails_env == ‘production’ {}の中の処理を実行することができます。
つまり、開発環境のように3000ポートで起動するのではなく、ソケットをバインドして、バックグラウンドで実行するようになります。
Pumaの再起動方法
Railsのコードを修正した場合、Pumaを再起動する必要があります。
Pumaを再起動するには、バックグラウンドで動いているためプロセスを終了させる必要があります。
ps aux | grep puma
このコマンドを実行することで、Pumaのプロセス番号を取得することができるので、
kill <プロセス番号>
これで終了させることができます。
終了させたら、再度
rails s -e production
コマンドを実行することにより、修正したコードが反映されるようになります。
Nginx + React + Pumaで本番環境のVPSへと公開する方法まとめ
ReactとRuby on Railsで作ったアプリをNginxと連携させてVPSへと公開する方法についてざっくり解説してきました。
正直コマンド全てを1つ1つまで理解している訳ではありませんが、これくらいの理解で動かすことはできるようになりました。
Dockerを使わず、できるだけシンプルな構成にしたい場合は今回解説した方法でだいたいできるんじゃないかと思います。
もし、間違っている部分や、こうすればもっと簡単だよ〜みたいなのがあれば、TwitterのDMやお問い合わせフォームより教えていただけると嬉しいです!