Pull request を作成したら、レビュアーがすぐに動作確認できるプレビュー環境が欲しい。Railway は、Pull Request (PR) ごとに独立した環境(データベース含む)を自動で作成・破棄してくれる PR Preview Environments を標準機能として備えています。GitHub Actions のワークフローを書く必要はありません。
今回、Rails 8.1 + PostgreSQL のミニマルなアプリを Railway にデプロイし、PR プレビュー環境が動くところまでを検証しました。
- GitHub: rails-preview-demo
Railway とは
Railway は、アプリケーションのデプロイとインフラ管理を簡素化するクラウドプラットフォームです。
| 特徴 | 説明 |
|---|---|
| 自動ビルド | ソースコードからビルド方法を自動検出(Dockerfile、Nixpacks) |
| PR プレビュー | PR ごとに独立した環境を自動作成・破棄 |
| ビジュアルキャンバス | サービス間の接続をグラフィカルに管理 |
| 内蔵データベース | PostgreSQL、MySQL、Redis、MongoDB をワンクリックで追加 |
| オートスケール | CPU/RAM のスケーリングとレプリカ管理 |
| 従量課金 | 使った分だけ。フリープランあり |
技術スタック
検証に使用した技術スタックです。
| 技術 | バージョン |
|---|---|
| Ruby | 3.4.8 |
| Rails | 8.1.2 |
| PostgreSQL | 17 |
アプリの構成
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) |
/posts | GET | 投稿一覧 |
/posts/new | GET | 新規作成フォーム |
/posts/:id | GET | 投稿詳細 |
/posts/:id/edit | GET | 編集フォーム |
/up | GET | ヘルスチェック(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"]ポイントは ENTRYPOINT と CMD の分離です。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
}
}| 設定 | 値 | 説明 |
|---|---|---|
builder | DOCKERFILE | Dockerfile を使ってビルド |
healthcheckPath | /up | Rails のヘルスチェックエンドポイント |
healthcheckTimeout | 300 | ヘルスチェックのタイムアウト(秒) |
restartPolicyType | ON_FAILURE | 失敗時に再起動 |
restartPolicyMaxRetries | 5 | 最大リトライ回数 |
2. Dashboard でプロジェクトを作成する
Railway の Dashboard で以下の手順を実行します。
- 新規プロジェクト作成 — GitHub リポジトリを接続
- PostgreSQL を追加 — プロジェクトのキャンバスから「Add Service」→「PostgreSQL」
- 環境変数を設定 — アプリサービスの Variables タブで以下を設定
| 変数 | 値 |
|---|---|
DATABASE_URL | ${{Postgres.DATABASE_URL}} |
RAILS_MASTER_KEY | config/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.json に startCommand を設定していました。
{
"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/rails と server かどうかで db:prepare の実行を判断しますが、startCommand が渡された場合は引数が 1 つの文字列になるため、条件に合致せず db:prepare がスキップされます。
解決策
startCommand を削除し、Dockerfile の ENTRYPOINT + CMD に任せます。前述の railway.json から startCommand を除いた構成です。
ENTRYPOINT(docker-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 ごとのプレビュー環境を構築してみた、現場からお送りしました。