Rails アプリを Railway にデプロイして Pull Request ごとのプレビュー環境を手に入れる

重岡 正 ·  Thu, February 5, 2026

Pull request を作成したら、レビュアーがすぐに動作確認できるプレビュー環境が欲しい。Railway は、Pull Request (PR) ごとに独立した環境(データベース含む)を自動で作成・破棄してくれる PR Preview Environments を標準機能として備えています。GitHub Actions のワークフローを書く必要はありません。

今回、Rails 8.1 + PostgreSQL のミニマルなアプリを Railway にデプロイし、PR プレビュー環境が動くところまでを検証しました。

Railway とは

Railway は、アプリケーションのデプロイとインフラ管理を簡素化するクラウドプラットフォームです。

特徴説明
自動ビルドソースコードからビルド方法を自動検出(Dockerfile、Nixpacks)
PR プレビューPR ごとに独立した環境を自動作成・破棄
ビジュアルキャンバスサービス間の接続をグラフィカルに管理
内蔵データベースPostgreSQL、MySQL、Redis、MongoDB をワンクリックで追加
オートスケールCPU/RAM のスケーリングとレプリカ管理
従量課金使った分だけ。フリープランあり

技術スタック

検証に使用した技術スタックです。

技術バージョン
Ruby3.4.8
Rails8.1.2
PostgreSQL17

アプリの構成

Post の CRUD を scaffold した最小構成のアプリです。

ルーティング

Rails.application.routes.draw do
  resources :posts
  get "up" => "rails/health#show", as: :rails_health_check
  root "posts#index"
end
パスメソッド説明
/GET投稿一覧(posts#index
/postsGET投稿一覧
/posts/newGET新規作成フォーム
/posts/:idGET投稿詳細
/posts/:id/editGET編集フォーム
/upGETヘルスチェック(200 or 500)

/up は Rails 組み込みのヘルスチェックエンドポイントで、アプリが正常に起動していれば 200 を返します。Railway のヘルスチェックにそのまま使えます。

Dockerfile

Rails 8.1 が生成するマルチステージ Dockerfile をそのまま使用しています。

ARG RUBY_VERSION=3.4.8
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base
WORKDIR /rails
 
# ... (base packages, jemalloc, environment variables)
 
FROM base AS build
# Install build dependencies, gems, precompile assets
COPY . .
RUN bundle install
RUN bundle exec bootsnap precompile -j 1 app/ lib/
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
 
FROM base
# Non-root user, copy artifacts
COPY --chown=rails:rails --from=build /rails /rails
 
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
EXPOSE 3000
CMD ["./bin/rails", "server"]

ポイントは ENTRYPOINTCMD の分離です。bin/docker-entrypoint は、rails server の起動前に自動で db:prepare を実行します。

#!/bin/bash -e
 
if [ "${@: -2:1}" == "./bin/rails" ] && [ "${@: -1:1}" == "server" ]; then
  ./bin/rails db:prepare
fi
 
exec "${@}"

この仕組みは後述する Railway の設定で重要になります。

Railway へのデプロイ

1. railway.json を作成する

リポジトリのルートに railway.json を追加します。

{
  "$schema": "https://railway.com/railway.schema.json",
  "build": {
    "builder": "DOCKERFILE"
  },
  "deploy": {
    "healthcheckPath": "/up",
    "healthcheckTimeout": 300,
    "restartPolicyType": "ON_FAILURE",
    "restartPolicyMaxRetries": 5
  }
}
設定説明
builderDOCKERFILEDockerfile を使ってビルド
healthcheckPath/upRails のヘルスチェックエンドポイント
healthcheckTimeout300ヘルスチェックのタイムアウト(秒)
restartPolicyTypeON_FAILURE失敗時に再起動
restartPolicyMaxRetries5最大リトライ回数

2. Dashboard でプロジェクトを作成する

Railway の Dashboard で以下の手順を実行します。

  1. 新規プロジェクト作成 — GitHub リポジトリを接続
  2. PostgreSQL を追加 — プロジェクトのキャンバスから「Add Service」→「PostgreSQL」
  3. 環境変数を設定 — アプリサービスの Variables タブで以下を設定
変数
DATABASE_URL${{Postgres.DATABASE_URL}}
RAILS_MASTER_KEYconfig/master.key の値

DATABASE_URL には Railway の変数参照構文 ${{Postgres.DATABASE_URL}} を使います。これにより、PostgreSQL サービスの接続情報が自動で注入されます。

3. デプロイを確認する

GitHub リポジトリに push すると Railway が自動でビルド・デプロイを実行します。デプロイが完了すると *.up.railway.app のドメインでアプリにアクセスできます。

PR Preview Environments

ここからが本題です。Railway は PR ごとに独立したプレビュー環境を自動で作成する機能を持っています。

設定方法

Project Settings → Environments で Enable PR Environments を有効にするだけです。GitHub Actions のワークフローは不要です。

動作の仕組み

PR を作成すると、Railway は以下を自動で実行します。

ステップ内容
1. 環境の作成PR 専用の独立した環境を作成
2. DB の複製新しい PostgreSQL インスタンスをプロビジョニング
3. ビルドPR ブランチのコードで Dockerfile をビルド
4. DB マイグレーションdb:prepare を実行(docker-entrypoint 経由)
5. URL の発行*.up.railway.app のユニークな URL を割り当て
6. GitHub への通知PR にデプロイ結果をコメント

PR がマージまたはクローズされると、プレビュー環境は自動的に削除されます。

実際の PR プレビュー

PR #5 では、Railway のボットが以下のようなコメントを自動で投稿しました。

Deployed to the rails-preview-demo-pr-5 environment in rails-preview-demo

  • Service: rails-preview-demo — Status: Success
  • Web URL: https://rails-preview-demo-rails-preview-demo-pr-5.up.railway.app

PR ごとに独立した URL が発行されるため、レビュアーはリンクをクリックするだけで変更内容を確認できます。DB も独立しているので、テストデータの作成や破壊的な操作も安心して行えます。

Bot PR Environments — AI ツール利用時の注意点

Claude Code や GitHub Copilot などの AI ツールを使ってコミットや PR を作成する場合、Railway はそれらを Bot PR として分類します。デフォルトでは Bot PR に対してプレビュー環境は作成されません。

AI ツールで作成した PR にもプレビュー環境を有効にするには、Project Settings → Environments で Bot PR Environments を有効にしてください。

これを忘れると、AI ツールが作成した PR だけプレビュー環境が立ち上がらないという現象に遭遇します。

ハマりどころ — startCommand と docker-entrypoint の競合

検証中に遭遇した問題を共有します。

問題

当初、railway.jsonstartCommand を設定していました。

{
  "deploy": {
    "startCommand": "bin/rails db:prepare && bin/rails server -b ::",
    "healthcheckPath": "/up"
  }
}

この設定では、本番環境のデプロイは成功するが、プレビュー環境のデプロイが失敗するという現象が発生しました。

原因

Railway は startCommand を Dockerfile の ENTRYPOINT に対するシェル引数として渡します。つまり、実際に実行されるコマンドは以下のようになります。

/rails/bin/docker-entrypoint "bin/rails db:prepare && bin/rails server -b ::"

docker-entrypoint は最後の 2 引数が ./bin/railsserver かどうかで db:prepare の実行を判断しますが、startCommand が渡された場合は引数が 1 つの文字列になるため、条件に合致せず db:prepare がスキップされます。

解決策

startCommand を削除し、Dockerfile の ENTRYPOINT + CMD に任せます。前述の railway.json から startCommand を除いた構成です。

  • ENTRYPOINTdocker-entrypoint)が rails server を検出して db:prepare を実行
  • CMD./bin/rails server)が Puma を起動
  • Puma はデフォルトで 0.0.0.0 にバインドし、Railway が設定する PORT 環境変数を読む

Dockerfile が正しく構成されていれば、Railway 側で startCommand を指定する必要はありません。Rails 8.1 が生成する Dockerfile はそのまま Railway で動作します。

まとめ

Railway を使えば、Rails アプリの PR プレビュー環境を最小限の設定で実現できます。

  • 必要な設定ファイルは railway.json の 1 つだけ
  • GitHub Actions のワークフローは不要
  • PR ごとに DB 込みの独立した環境が自動で立ち上がる
  • マージ/クローズ時に自動で環境が削除される
  • AI ツール利用時は Bot PR Environments の有効化を忘れずに
  • startCommand は使わず、Dockerfile の ENTRYPOINT + CMD に任せる

PR プレビュー環境があるとレビューのフローが変わります。「ローカルでブランチを pull して動かす」という手間がなくなり、PR のリンクをクリックするだけで変更を確認できます。

以上、Rails を Railway にデプロイして PR ごとのプレビュー環境を構築してみた、現場からお送りしました。

参考情報