きり丸の技術日記

技術・エンジニアのイベント・資格等はこちらにまとめる予定です

Spring Profilesで環境ごとの設定ファイルを読み込む(SpringBoot2.4の変更も記載)

きり丸アドベントカレンダー2020の15記事目です。


作成したアプリケーションを各環境にデプロイする際、2つの考え方があります。

  1. 各環境用に設定ファイルを書き換えてデプロイする
  2. 各環境用に複数の設定ファイルを用意し、デプロイ後に読み込む設定ファイルだけ切り替える

前者でAnsible等の自動化をしている場合は問題ありませんが、手動でやっている場合は常に失敗するリスクがあります。私は10回に1,2回の頻度でデプロイ失敗していました。

後者では、初回起動時に設定値が以上で失敗することはありましたが、2回目以降のデプロイで失敗したことはありません。

今回の記事では後者でデプロイができるように、Springでの起動時に設定ファイルを指定、または環境変数で設定ファイルを指定して起動する方法をまとめます。

なお、Spring Boot2.3以前と2.4以降では設定ファイルの書き方が異なるので、現在のバージョンを意識してください。

環境

  • Spring Boot
    • 2.3.4 RELEASE
    • 2.4.0
  • Java
    • 15

全環境の設定ファイルの準備

設定ファイルの読み込み方法


Spring Bootは、resourcesディレクトリ直下にある「application-*.yml」を設定ファイルとして読み込みます。

デフォルトは、「application.yml」を読み込みます。

src/main/resources/application.yml # デフォルトの起動対象

設定ファイル内で有効設定ファイルの指定


設定ファイル内で「spring.profiles.active」を指定すると、activeに指定されている設定ファイルを読み込みます。

私は「application.yml」に下記を書き込んでおき、「application-local.yml」を読み込ませています。そうすると、環境ごとにファイルが並ぶので可読性が高くなります。

# application.yml
spring.profiles.active: local
application.yml 
application-local.yml # ローカル起動用
application-prd.yml # 本番環境用
application-mock.yml # モック用

ただし、このやり方を行うと、テストで設定ファイルを選択してテストする方法は使えなくなるようです(要検証)

強烈に困っているわけではないので、可読性優先して調査放棄していますが、気を付けてください。テストのみ発生するもので、実運用には何にも問題ありません。

1. テストで「prd」設定ファイルを指定
2. 「application-prd.yml」を読み込む
3. **なぜか**デフォルトの「application.yml」を読み込みに行く
4. 有効設定ファイルを「local」に上書きする
5. 「application-local.yml」で上書きされる

設定ファイルを指定した起動

JVMのパラメータにプロファイルを渡して起動する方法


「-Dspring.profiles.active」で有効設定ファイルを指定できます。ただし、こちらは起動のたびにパラメータを指定する必要があるので、検証用でしか使用したことはありません。

java -jar -Dspring.profiles.active={プロファイル名} {jar名}
# java -jar -Dspring.profiles.active=prd jp.co.kelly-0.0.1-SNAPSHOT.jar

環境変数での起動方法


よく使用しているのはこちらの方法です。起動する環境に次の環境変数を設定しておきます。Ansible等で環境に自動設定すると便利です。

export SPRING_PROFILES_ACTIVE={有効設定ファイル}
# export SPRING_PROFILES_ACTIVE=prd

Dockerで起動する場合も、起動するコンテナ内に環境変数を与える必要があります。-eでパラメータを渡してください。

docker run -e SPRING_PROFILES_ACTIVE=prd ...{起動するdockerイメージ等々}

複数の設定ファイル読み込ませる

カンマ区切りで渡すと、渡した順番で設定ファイルを読み込みます。設定が重複した場合、後に読み込ませた設定値が優先されて設定されます。

カンマ区切りはJVMパラメータだけでなく、環境変数でも有効です。

java -jar -Dspring.profiles.active=prd,mock {jar名}
java -jar -Dspring.profiles.active=prd,mail-replace {jar名}

複数のプロファイル読み込みのユースケース


  • 性能試験用に一時的に外部システムをモックにしたい
    • 性能試験は一気通貫でやるべきですが、高負荷試験中にアクセス数で課金されるシステムがあると厳しい。
  • 対向システムが環境をリプレイスするが、本格運用前に一時的に接続確認したい
    • 新システムへの接続がうまくいかず、旧システムへ接続するときに、簡単に切り戻せる
    • Gitプッシュでバージョンを増やしている場合、Pushせずに変更できるので無駄なバージョンアップが減る

設定ファイルをまとめた設定ファイルを作成する(2.3以前のみ有効)

DBへのタイムアウト値やアプリケーションの名前等々、共通的に使用できる項目があります。それを「application-common.yml」と定義して、複数ファイルを読み込んでも期待とおりの動きになります。

java -jar -Dspring.profiles.active=prd,common

しかし、プロファイルを分割すると各環境に環境変数を再設定する必要があり、運用が面倒になります。「spring.profiles.include」を設定すると設定ファイルをまとめた設定ファイルを作成できます。

私は外部システムやDBの設定ファイル、共通ファイルに分割し、まとめた設定ファイルを使用しています。

spring:
  profiles:
    include:
      - common # 共通
      - external-ut # 外部システム
      - repository-ut # DBの設定

Spring Boot2.4以降の変更点

公式のSpringブログに記載されていた後者が特に問題です。

1. Documents will be loaded in the order that they’re defined.
2. Profiles can no longer be activated from profile specific documents.

上記に記載した「spring.profile.active」を使用して環境を指定し、別のファイルをincludeで使用する方法は2.4以降では使えなくなりました。

includeの代わりにどうするか


「設定ファイルをまとめた設定ファイル」を作成する方法はないようです。

なので代替案として、「application.yml」に「spring.profiles.group.」を設定してください。

下記設定は、「common」「local」「prd」グループを設定したうえで、そこから読み込むファイルを設定します。

spring:
  profiles:
    group:
      common:
        - common-mybatis
        - common-thymeleaf
      local:
        - database-local
        - common
      prd:
        - database-prd
        - common

この状態で有効設定ファイルを「local」で起動すると、以前と同様に読み込むことができます。

java -jar -Dspring.profiles.active=local {jar名}
The following profiles are active: local,database-local,common,common-mybatis,common-thymeleaf

2.4以降でも2.3の設定で使用したい場合

Spring Bootを2.4にアップデートしても、2.3の設定で動作させたい場合は、次の設定を「application.yml」に設定してください。

spring.config.use-legacy-processing: true

ただし、公式Springブログでは、「もしこの設定をする場合、私たちが見逃した特殊なユースケースなのでGitHubのissueを上げて連絡してください」とのことでした。

原文引用:

If you do find you need to switch to legacy processing because we’ve missed a specific use-case, please raise an issue on GitHub and we’ll try to address it.

ソースコード

アドベントカレンダー15日目。
github.com

終わりに

簡単にまとめる予定でしたが、実際には職場で構築してもらった設定に助けてもらったところがあり、理解していないことも多かったです。すでに知っているものに関しても自分で再度まとめると、理解度を自分に問うことができるので非常に勉強になります。

あと、Spring Bootの2.4以降の仕様変更で動かなかった件は4-5時間くらい調査に持っていかれました…。ずっと自分の環境構築不備の方向から探ってたので、気付くのに時間かかってしまいました。

職場で行うSpring Bootのアップデート時にこの仕様変更を踏まなくてよかったと、前向きにとらえることにします。


この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。

参考記事

Spring Profilesのリファレンス www.baeldung.com

Spring Bootの2.4.Xのリファレンス https://docs.spring.io/spring-boot/docs/2.4.x/reference/html/spring-boot-features.html#boot-features-profiles

Spring Bootの設定値一覧 docs.spring.io

公式Springブログ:Spring Bootの設定方法が2.4.ゼロから変わったことに対する記事 spring.io

Stackoverflow:Including profiles in spring boot 2.4.0 version https://stackoverflow.com/questions/64907675/including-profiles-in-spring-boot-2-4-0-version

類似記事

きり丸アドベントカレンダー2020 adventar.org

きり丸のHerokuページ
https://kirimaru-todoapp.herokuapp.com/

16日目のアドベントカレンダーの記事 https://nainaistar.hatenablog.com/entry/2020/12/16/083000nainaistar.hatenablog.com

f:id:nainaistar:20201109133010p:plain