初めに
プロジェクトで担当したアプリは、Ruby on Railsで開発されており、DB接続等シークレットをRuby on Railsのcredentialで保持していた。
今回、Beanstalkで動作していたアプリをFargateに切替える作業があり、次の改修を合わせて実施した。
シークレットの保持をRuby on Railsのcredentialから、AWSのSecrets Managerに変更
改修理由は以下の通り
- 暗号化したテキストファイルとは言え、ソースリポジトリにcredentialを保持しているのは問題
- 現状ではシークレット情報の変更が手間。暗号化ファイルを復号し、書き換えて暗号化を再実施という手順を踏む必要がある。
本対応を実施する中で、問題が発生したため問題内容と解決方法について記載しておく。
当初実施した改修内容
- Ruby on Railsのcredential機能で作成された、暗号化ファイル(
/config/credentials/{環境名}.yml.enc
)を削除 - シークレットの読み込み箇所を修正
修正前
Credentials.env[:項目名]
修正後
ENV['項目名']
問題内容
コンテナイメージをbuildする際にDockerfileの次のコマンドでエラーとなった
Dockerfile
RUN rm -rf tmp log \ && mkdir tmp log \ && ASSETS_PRECOMPILE=1 RAILS_ENV=production bundle exec rails assets:precompile \ && rm -rf tmp/* log/* node_modules
エラーメッセージ
#35 [stage-1 21/36] RUN rm -rf tmp log && mkdir tmp log && ASSETS_PRECOMPILE=1 RAILS_ENV=production DB_ADAPTER=nulldb bundle exec rails assets:precompile && rm -rf tmp/* log/* node_modules #35 5.007 rails aborted! #35 5.008 TypeError: Cannot load database configuration: #35 5.008 /home/app/webapp/config/database.yml:22:in `[]` #35 5.008 /home/app/webapp/config/environment.rb:5:in
原因
シークレットの読み込みは、デプロイ完了後にアプリが起動するタイミングと考えていた。
しかし、ビルドパラメータにaseets:precompile
が設定されており、ビルド時にシークレットを読み込んでいた。
Rails credential利用時は問題なかったが、Secrets Manager利用ソースはアプリ起動時からシークレット(環境変数)が読み込めるため、ビルド時にシークレット(環境変数)が読み込めずエラーとなったと推測される。
対応内容について
原因に記載した通り、ビルド時に実際のDB接続は発生しないが、precompile時に何らかの設定値が必要と推測した。
デフォルト値にダミー値を設定しておき、環境変数が読み込めなかった場合にダミー値を設定するように修正。
エラーが発生した該当ソース(database.yml)の内容
username: <%= ENV['DB_USERNAME'] %> password: <%= ENV['DB_PASSWORD'] %> host: <%= ENV['DB_HOST'] %>
改修内容
username: <%= ENV['DB_USERNAME'] || 'dummy_user' %> password: <%= ENV['DB_PASSWORD'] || 'dummy_pass' %>
上記対応を行うことで無事にコンテナイメージのビルドが完了した。