初めに

プロジェクトで担当したアプリは、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' %>

上記対応を行うことで無事にコンテナイメージのビルドが完了した。