SpringBootで環境変数を扱う際の注意点

SpringBootのWebアプリで環境変数に関する学びがあったので、その内容についてまとめます。

概要

先に概要をお伝えします。

  • SpringBootでは環境変数を読み取る際に変数名が完全一致していなくても変数名を調整して取得してくれる機能がある
  • 設定ファイルと環境変数で同じ名称があった場合は環境変数が優先される

背景

  • 開発しているWebアプリで、ステージング環境と本番環境で背景色を変更したい、という要望があった
  • 環境によって値が変わるので環境変数を使用して対応していた
  • ある時、ステージング環境のみ値を変更しようとしたところ修正の反映がされず、色々と調べていたところ環境変数に関する機能があることを知った

環境

  • 開発対象のアプリはSpringBoot(Java)を用いたWebアプリ
  • 動作環境はAWS ECS
  • インフラ環境はTerraformで構築
  • 環境変数はTerraformを用いてECSの環境変数に値をセット

実際のコードと事象

SpringBootでは、設定ファイルとしてapplication.propertiesまたはapplication.yamlを環境毎に作成可能(例えば、ステージング環境はapplication-stg.properties、本番環境はapplication-prd.propertiesなど)。

元々は、それぞれの設定ファイルで以下のように画面背景色の値を環境変数にて設定。

# メイン背景色  
app.background-color=${APP_BACKGROUND_COLOR}

プログラムでは、Thymeleaf(SpringBootのテンプレートエンジン)にて、背景色用のCSS変数に、設定ファイルから取得してきた値をセット。

<style>  
  :root {  
    --background-bg-color:[[${@environment.getProperty('app.background-color')}]]; 
  }
</style>

CSSでは変数を使用して背景色を指定。

body {
	background-color: var(--background-bg-color);
}

この状態で、TerraformにてECSの環境変数APP_BACKGROUND_COLORに環境毎のカラーコードの値を入れることで、ステージング環境と本番環境で背景色を変える実装を実現していました。

ステージング環境の設定ファイルにカラーコードを直接指定

ここで、ステージング環境の背景色を変更したい要件が出てきたので、設定ファイルから背景色を変更。

application-stg.properties

# メイン背景色  
app.background-color=#ffffff

※本来であれば環境変数の値を変えるべきですが、諸事情あってTerraformからの適用が難しいタイミングだったので、設定ファイルの値を直接変更しました。

これで、カラーコード白を設定したので、背景色が白になるはず。
しかし、ビルド・デプロイした結果、背景色は白になっておらず、元の背景色のままでした。

なぜ???
と思い調べていたところ、SpringBootには環境変数読み取り時に変数名を調整してくれる機能があること、そして設定ファイルと環境変数で同じ名前がある場合は環境変数が優先されることを知りました。

整理

まず、Thymeleafで指定している${@environment.getProperty('app.background-color')}は、設定ファイル(及び環境変数)のapp.background-colorの値を取得しています。

この時、設定ファイルの内容は以下。

app.background-color=#ffffff

環境変数は以下。

APP_BACKGROUD_COLOR=#f0f8ff

この状態でビルド・デプロイした結果、背景色に白(#ffffff)ではなく、環境変数の方のカラーコード(ここでは#f0f8ff)が適用されていました。

つまり、コード上はapp.background-colorと指定して取得した場合に、APP_BACKGROUD_COLORの環境変数の値が取得できるという事。そして、設定ファイルと環境変数で同じ値がある場合に、環境変数の方が優先されるという事が分かりました。

まとめ

今回の件は、本来であれば環境変数の値を変更するか、不要な環境変数の値を事前に削除しておけば何事もなく背景色を変更できたかと思います。その場しのぎの修正対応はあまり良い結果にならないという事なのでしょう。
とはいえ、今回の事象によってSpringBootに関して一つ知識を増やすことができたので、それはそれで良かったです。SpringBootを使って開発をしている人の参考になれば幸いです。

参考

https://docs.spring.io/spring-boot/3.4/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding

https://docs.spring.io/spring-boot/3.4/reference/features/external-config.html#features.external-config.typesafe-configuration-properties.relaxed-binding