Rails アプリをデプロイする
Rails 7.1 以降は本番用の Dockerfile を生成し、Lizard (lizard.build) はその内容どおりにビルドします。このイメージは gem をインストールし、アセットをプリコンパイルし、サーバーが起動するたびに bin/rails db:prepare を実行します。RAILS_MASTER_KEY とデータベース URL を設定し、Rails 8 では lizard up --port 8080(Thruster 用に HTTP_PORT=8080 も設定)、Rails 7.1 と 7.2 では lizard up --port 3000 を実行します。Dockerfile がない場合、lizardpack はポート 3000 で動くシンプルな Ruby イメージをビルドします。
テスト状況: Rails が生成する Dockerfile、bin/docker-entrypoint、config/puma.rb、database.yml、Lizard のビルドとポートのルール、そして Dockerfile のない Rails アプリに対する lizardpack のプランを確認しました。このガイドの Rails デプロイ手順は、まだ最初から最後まで試していません。
始める前に
- PostgreSQL(
pggem)を使い、生成されたDockerfileとbin/docker-entrypointが残っている Rails 7.1 以降のアプリ。古いアプリでは、dockerfile-rails gem でこれらを生成できます。bundle add dockerfile-rails --group developmentを実行してから、bin/rails generate dockerfileを実行してください。 - 手元のコンピューターにある
config/master.key、またはアプリのSECRET_KEY_BASE。 x86_64-linuxプラットフォームを含むGemfile.lock。bundle lock --add-platform x86_64-linuxで追加し、ファイルをコミットします。lizard loginでサインイン済みで、Pro または 7 日間の Pro トライアル(カードが必要)を利用している Lizard CLI。料金を参照してください。
Lizard が Rails アプリをビルドする方法
| アプリにあるもの | Lizard がビルドするもの | サービスポート |
|---|---|---|
Rails 8 の Dockerfile(EXPOSE 80、CMD ["./bin/thrust", "./bin/rails", "server"]) | アプリの Dockerfile をそのまま | 8080(HTTP_PORT=8080 を設定) |
Rails 7.1 または 7.2 の Dockerfile(EXPOSE 3000) | アプリの Dockerfile をそのまま | 3000 |
| Dockerfile なし | lizardpack の Ruby イメージ。後述を参照 | 3000 |
サービスのビルドコマンドと起動コマンドは空のままにしてください。どちらかが設定されていると、Lizard はアプリの Dockerfile を使わずに、そのコマンドから独自の Dockerfile を生成します。そのイメージに入っているのは Ruby ではなく Node.js です。起動コマンドはイメージの entrypoint も置き換えるため、db:prepare が実行されなくなります。ビルド決定順序を参照してください。
Rails 8 は Thruster を起動します。Thruster はポート 80 で待ち受け、その背後のポート 3000 で Puma を実行します。イメージは非 root ユーザー(USER 1000:1000)で動作し、非 root プロセスには 1024 未満のポートを開く権限がない場合があります。HTTP_PORT=8080 を設定すると、Thruster は常に開けるポートに移ります。
プロジェクトとデータベースを作成する
アプリのルートディレクトリから実行します:
lizard init --name rails-app
lizard add --service web
lizard add postgresManaged Postgres は postgres スーパーユーザーとして接続するため、db:prepare は Rails が求めるデータベースを作成できます。
シークレットを設定してデプロイする(Rails 8)
Rails 8 の本番用 database.yml は、primary、cache、queue、cable の 4 つのデータベースを定義しています。DATABASE_URL が置き換えるのは primary だけです。それ以外について、Rails は CACHE_DATABASE_URL、QUEUE_DATABASE_URL、CABLE_DATABASE_URL を読み取ります。4 つすべてを、データベース名を変えて同じ Postgres に向けてください:
PG='postgresql://postgres:${{postgres.PGPASSWORD}}@${{postgres.LIZARD_PRIVATE_DOMAIN}}:5432'
lizard secrets set \
RAILS_MASTER_KEY="$(cat config/master.key)" \
DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' \
CACHE_DATABASE_URL="$PG/rails_cache" \
QUEUE_DATABASE_URL="$PG/rails_queue" \
CABLE_DATABASE_URL="$PG/rails_cable" \
HTTP_PORT=8080 \
SOLID_QUEUE_IN_PUMA=true \
--service web
lizard up --service web --port 8080- シングルクォートで囲むと、シェルは
${{…}}を解釈しません。Lizard はこれらの 参照 をデプロイ時に解決し、プロジェクトのプライベートネットワークを使います。 SOLID_QUEUE_IN_PUMA=trueを設定すると Puma が Solid Queue の worker を実行するため、Active Job のジョブは web サービスの中で実行されます。設定しないと、キューに入ったジョブはいつまでも待ち続けます。RAILS_MASTER_KEYの代わりにSECRET_KEY_BASEを使うのは、アプリがほかの暗号化された credentials を読まない場合だけにしてください。
シークレットを設定してデプロイする(Rails 7.1 と 7.2)
これらのバージョンはデータベースを 1 つだけ使います:
lizard secrets set \
RAILS_MASTER_KEY="$(cat config/master.key)" \
DATABASE_URL='${{postgres.DATABASE_PRIVATE_URL}}' \
--service web
lizard up --service web --port 3000デプロイのたびに行われること
lizard up はディレクトリをアップロードします。git リポジトリ内では .gitignore に書かれたものをスキップします。Rails の .gitignore と .dockerignore は、どちらも config/master.key と .env* ファイルを除外しています。Lizard は Dockerfile のビルドに COMMIT_SHA 以外の変数を渡さないため、ビルドは SECRET_KEY_BASE_DUMMY=1 でアセットをプリコンパイルします。
起動時に、bin/docker-entrypoint は ./bin/rails db:prepare を実行します。これは存在しないデータベースを作成し、新しいデータベースにスキーマを読み込み、保留中のマイグレーションを実行します。再起動を含め、コンテナが起動するたびに実行されます。マイグレーションは、新旧両方のコードで安全に実行できるようにしてください。
git push to deploy を使う場合は、lizard up を実行する代わりに、アプリを GitHub に push して リポジトリを接続 します。同じシークレットとポートを設定してください(lizard port 8080 --service web)。生成された Dockerfile には bundle install のステップがあるため、Lizard はその内容どおりに使います。
動作を確認する
lizard logs --build --service web
lizard logs --service web --tail 100
lizard domain --service webRails 7.1 以降は、アプリが起動すると /up に HTTP 200 で応答します。https://<your-domain>/up を開き、続いてデータベースから読み取るページを開いてください。ランタイムログには db:prepare の出力が表示され、その後に Puma の起動が表示されるはずです。
Dockerfile がない場合
lizardpack は Gemfile を見つけると Ruby アプリとしてビルドします:
- Ruby のバージョン:
.ruby-version、なければGemfileのruby行、それもなければ3.4。使われるのはメジャーとマイナーだけで、3.4.1はruby:3.4-slim上でビルドされます。 build-essentialとlibpq-devをインストールしてから、bundle installを実行します。- 起動: Procfile の
web:行。なければ、config.ruとRakefileがある場合にbundle exec rails server -b 0.0.0.0。ポートは3000です。
このイメージは RAILS_ENV を設定せず、アセットのプリコンパイルもデータベースの準備も行わないため、本格的な Rails サイトよりも小さなアプリや API に向いています。.ruby-version には 3.4.1 のように数字だけを書いてください。rails new は ruby-3.4.1 と書き込み、lizardpack はそれを存在しないイメージ名に変えてしまいます。ランタイムバージョンを参照してください。
よくある問題
| 症状 | 対処 |
|---|---|
bundle install が失敗し、bundle がほかのプラットフォームにしか対応していないと表示される | bundle lock --add-platform x86_64-linux を実行し、Gemfile.lock をコミットします。 |
Missing secret_key_base、または credentials の復号に失敗する | web サービスに、config/master.key の値で RAILS_MASTER_KEY を設定します。 |
cache、queue、cable の接続が /var/run/postgresql などのローカルソケットに向かう | CACHE_DATABASE_URL、QUEUE_DATABASE_URL、CABLE_DATABASE_URL を設定します。 |
ログにポート 80 の bind: permission denied が表示される | HTTP_PORT=8080 を設定し、サービスポートを 8080 にします。 |
| デプロイがいつまでも healthy にならない | サービスポートが上の表と一致しているか確認します: lizard port --service web。サービスが healthy にならないを参照してください。 |
| ジョブがキューに残ったままになる | SOLID_QUEUE_IN_PUMA=true を設定します。web プロセスとは別にジョブを実行するには、dockerfilePath=Dockerfile と startCommand=./bin/jobs を指定した 2 つ目のサービスを worker mode で追加します。 |
| アップロードしたファイルがデプロイ後に消える | Active Storage の local サービスはコンテナ内に書き込みます。S3 互換の Managed Object Storage を amazon サービスで使ってください。 |
アプリが Sidekiq や Redis の Action Cable アダプターを使う場合は、Managed Redis を追加し、必要な各サービスに REDIS_URL='${{redis.REDIS_PRIVATE_URL}}' を設定してください。
関連項目
更新日