[Rails 7.0.8]Missing `secret_key_base` for ‘production’ environment...
はじめに
アプリのRailsバージョンを7.1から7.0.8にバージョンダウンし、ディプロイしたらタイトルのエラーが出たのでメモとして残します。
1.109 (See full trace by running task with --trace) ------ Dockerfile:51 -------------------- 49 | 50 | # Precompiling assets for production without requiring secret RAILS_MASTER_KEY 51 | >>> RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile 52 | 53 |-------------------- error: failed to solve: process "/bin/sh -c SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile" did not complete successfully: exit code: 1 error: exit status 1
経緯
Rails7.1でデフォルトのDockerfileを使って開発とデプロイを行ってましたが、とある機能の実装に当たって導入しようとしているGemがRails7.0.8までしか対応していないため、7.0.8にダウングレードすることになりました。
その機能の実装を終え、本番にデプロイしようとしたら以上のエラーが出ました。
調べたこと
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
エラー文を見ると、Dockerfileの51行目でエラーが発生したことが分かります。
該当するコマンドはRUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
になります。
Rails 7.1以降でrails new
コマンドを使用してアプリケーションを生成すると、この行を含むDockerfileが自動的に含まれます。
このコマンドは、Dockerイメージのビルド時にアセットのプリコンパイルを行うためのものです。
SECRET_KEY_BASE_DUMMY=1
の役割:
- アセットのプリコンパイル処理中に
SECRET_KEY_BASE
が必要となる場合があります。 - この環境変数にダミー値を設定することで、ビルド時のエラーを回避します。
-
1
という値に特別な意味はなく、単なるプレースホルダーです。 - この
SECRET_KEY_BASE_DUMMY
値はビルド時のみ使用され、実際の運用環境では使用されません。 - 本番環境では、適切な
SECRET_KEY_BASE
を別途設定する必要があります。
この方法により、config/credentials.yml.enc
が存在する場合、実際のSECRET_KEY_BASE
がなくてもアセットのプリコンパイルが可能になりました。
エラーの背景
Rails 7.1以前では、本番環境でアプリケーションを実行する際にSECRET_KEY_BASE
環境変数が必要でした。Dockerfileでビルド時にこの変数が設定されていない場合、エラーが発生していました。→ いまここ
参考したPRとissue
Rails 7.1以前での代替案
Rails 7.1以前のバージョンでは、この特定の方法(SECRET_KEY_BASE_DUMMY=1
)を使用することは推奨されません。
互換性の問題:
- Rails 7.1より前のバージョンでは、
SECRET_KEY_BASE
に有効な値が必要です。 - ダミー値を使用すると、アセットのプリコンパイルや他の重要な操作で問題が発生する可能性があります。
- 古いバージョンでは、この方法を使うとセキュリティ上の脆弱性を引き起こす可能性があります。
解決法
- 環境変数を使用し
SECRET_KEY_BASE=
を指定
ARG SECRET_KEY_BASE
ENV SECRET_KEY_BASE=${SECRET_KEY_BASE}
RUN ./bin/rails assets:precompile
ビルド時に--build-arg SECRET_KEY_BASE=$SECRET_KEY_BASE
を指定します。
- アプリ内で設定を追加
config.secret_key_base = ENV['SECRET_KEY_BASE']
- コンソールから
secret_key_base
を取得
Rails.application.secret_key_base
# "######"
- 本番環境で
SECRET_KEY_BASE
を設定
本番環境では、環境変数SECRET_KEY_BASE
を設定します。
これでデプロイをうまく行きました。
ベストプラクティス
-
SECRET_KEY_BASE
はビルド時ではなく、実行時に設定するのが理想的です。 -
SECRET_KEY_BASE
を Dockerfile 内に直接記述することは避けてください。 - 開発環境では
config/master.key
やRAILS_MASTER_KEY
を使用します。docker run -p 3000:3000 -e RAILS_MASTER_KEY=$(cat config/master.key) --rm my_app
- 本番環境では、適切に管理された環境変数を使用します。
SECRET_KEY_BASE
の取得
development/test以外の環境におけるsecret_key_base値の取得元は、以下の上から順に試行されるようになります。
ENV["SECRET_KEY_BASE"]
credentials.secret_key_base
secrets.secret_key_base
なので、環境変数以外にもクレデンシャルから追加することができます。
EDITOR="code --wait" bin/rails credentials:edit --environment production
このコマンドは本番環境用の暗号化された認証情報を編集します。
VSCodeをエディタとして使用し、編集が完了するまで待機します。
対応するconfig/credentials/production.key
も生成されます。
コンソールから取得した値を追加します。
production:
secret_key_base: YOUR_SECRET_KEY_BASE
このファイルは本番環境ではRAILS_MASTER_KEY
環境変数またはconfig/master.key
に格納されたキーを使って復号化されるので、RAILS_MASTER_KEY
を環境変数として渡します。
終わりに
Rails 7.1以前のバージョンでDockerを使用する場合、こちらの代替方法を使用することで、アセットのプリコンパイルを行う際のエラーを解消することができました。誰かの参考になれば嬉しいです。
Discussion