Spring Bootのプロファイルとは、「ローカル」「検証」「本番」のような環境ごとに、設定や使うBeanを切り替えるための仕組みです。application-{プロファイル名}.yml に環境ごとの設定を書き、起動するときに spring.profiles.active で使うプロファイルを指定します。

プロファイルの切り替えそのものは簡単ですが、実務でつまずくのは、「結局どの値が使われているのか」がわからなくなることです。検索上位の記事には、Spring Boot 2系以前の古い書き方のままのものや、優先順位・環境変数での上書きに触れていないものも多くあります。この記事では、公式ドキュメント(Spring Boot 4.1系)で確認した優先順位と環境変数の命名規則を中心に、秘密の値の扱い、テストでの指定、Spring Boot 4系での注意点までを、一通り整理します。

プロファイル切り替えの早見表

やりたいこと 書き方
環境ごとの設定ファイルを作る application-dev.yml、application-prod.yml
起動時にプロファイルを指定する java -jar app.jar --spring.profiles.active=prod
環境変数で指定する SPRING_PROFILES_ACTIVE=prod
何も指定しないときの既定を決める spring.profiles.default: local
1つのファイルに環境ごとの設定を書く --- で区切り、spring.config.activate.on-profile: prod
設定値を環境変数で上書きする spring.datasource.url → SPRING_DATASOURCE_URL
プロファイルでBeanを切り替える @Profile("prod")、@Profile("!prod")
テストでプロファイルを指定する @ActiveProfiles("test")
今どのプロファイルが有効か確認する 起動ログの The following 1 profile is active: "prod"

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Spring Bootプロファイル切り替え|application.ymlと優先順位」

基本:application.ymlとapplication-{profile}.yml

共通の設定は application.yml に、環境ごとに違う設定だけを application-{プロファイル名}.yml に書きます。

src/main/resources
├── application.yml          # 全環境で共通の設定
├── application-local.yml    # 手元の開発用
├── application-dev.yml      # 検証環境用
└── application-prod.yml     # 本番用
# application.yml(共通)
spring:
  application:
    name: order-api
  profiles:
    default: local        # 何も指定しないときは local
server:
  port: 8080
app:
  page-size: 20
# application-prod.yml(本番だけ違う値)
spring:
  datasource:
    url: jdbc:postgresql://db.internal:5432/orders
    username: order_app
    password: ${DB_PASSWORD}     # 値そのものは書かず、環境変数から受け取る
app:
  page-size: 50
logging:
  level:
    root: warn

prod プロファイルで起動すると、application.yml の値が読み込まれたあと、application-prod.yml の値で上書きされます。上の例では、server.port は共通の8080のまま、app.page-size は50になります。

既定のプロファイルはspring.profiles.defaultで決める

何もプロファイルを指定しないと、default という名前のプロファイルが有効になります。application.yml に spring.profiles.active: local と書くより、spring.profiles.default: local と書く方が安全です。active と書くと、本番で指定し忘れたときにローカル用の設定で動いてしまいますが、default なら「何も指定されなかったとき」だけに効きます。

プロファイルの指定方法

方法 書き方 主な用途
起動引数 java -jar app.jar --spring.profiles.active=prod サーバーでの起動
Javaのシステムプロパティ java -Dspring.profiles.active=prod -jar app.jar 起動スクリプト
環境変数 SPRING_PROFILES_ACTIVE=prod コンテナ・クラウド
Maven ./mvnw spring-boot:run -Dspring-boot.run.profiles=dev 開発中の起動
Gradle ./gradlew bootRun --args='--spring.profiles.active=dev' 開発中の起動
IDE 実行構成の「Active profiles」や環境変数の欄 開発中の起動
設定ファイル spring.profiles.active: dev 通常は使わない(上の default を推奨)

複数のプロファイルは、カンマ区切りで指定できます(--spring.profiles.active=prod,metrics)。

有効なプロファイルは起動ログで確認する

Spring Bootは起動時に、有効なプロファイルをログに出します。Spring Bootのソースコード(SpringApplication)では、次の形式のメッセージになっています。

The following 1 profile is active: "prod"
No active profile set, falling back to 1 default profile: "default"

「設定が反映されない」と思ったら、まずこの行を確認します。意図したプロファイル名になっているか、つづりが違っていないかがわかります。

複数指定したときの順番(後勝ち)

公式ドキュメントでは、複数のプロファイルを指定したときは「後に書いたものが勝つ」と説明されています。spring.profiles.active=prod,live なら、application-prod.yml の値を、application-live.yml の値で上書きできます。

仕組み 書き方 動き
spring.profiles.include include: [common, local] 指定したプロファイルを追加する(active より前に入る)
プロファイルグループ spring.profiles.group.production: [proddb, prodmq] production を指定すると、proddb と prodmq もまとめて有効になる

1つのファイルに環境ごとの設定を書く(複数ドキュメント)

ファイルを分けずに、1つの application.yml を --- で区切って、環境ごとの設定を書くこともできます。

spring:
  application:
    name: order-api
  profiles:
    default: local
app:
  greeting: "共通の設定"
---
spring:
  config:
    activate:
      on-profile: local
app:
  greeting: "ローカル"
---
spring:
  config:
    activate:
      on-profile: "prod"
app:
  greeting: "本番"

このYAMLは、3つのドキュメントとして正しく読み込めることを確認しています(PythonのYAMLパーサーで構文を確認)。下にあるドキュメントほど後から読み込まれ、前の値を上書きします。

ルール(公式ドキュメント) 内容
区切り ちょうど3つのハイフン ---。前に空白を入れない
propertiesファイルの場合 #--- で区切る
条件の書き方 spring.config.activate.on-profile(プロファイル名)、on-cloud-platform(kubernetes など)
否定・組み合わせ on-profile: "!prod"、on-profile: "prod & cloud" のような式も書ける
書けない場所 on-profile で有効になるドキュメントの中に、spring.profiles.active・include・group は書けない

古い記事にある、次のような書き方に注意します。

# 古い書き方(Spring Boot 2.4で置き換えられた)
spring:
  profiles: prod

Spring Boot 2.4以降は、spring.config.activate.on-profile で書きます。

ファイルを分けるか、1ファイルにまとめるかは、チームで揃えます。環境の数が多い、または本番の設定を別に管理したい場合はファイルを分け、差分が数行なら1ファイルにまとめると見通しがよくなります。

外部設定の優先順位

Spring Bootは、設定値をいくつもの場所から読み込み、優先順位の高いもので上書きします。公式ドキュメントの一覧(下にあるものほど優先)から、よく使うものを抜き出すと次のとおりです。

優先順位(高い順) 設定の場所 例
1 テストでの指定 @TestPropertySource、@SpringBootTest(properties = ...)
2 コマンドライン引数 --server.port=9090
3 SPRING_APPLICATION_JSON JSONで渡す設定
4 Javaのシステムプロパティ -Dserver.port=9090
5 OSの環境変数 SERVER_PORT=9090
6 設定ファイル(下の表の順) application.yml など
7 @PropertySource @Configuration クラスに付けたもの
8 既定のプロパティ SpringApplication.setDefaultProperties

設定ファイルの中にも順番があります。

優先順位(高い順) ファイル
1 jarの外にある application-{profile}.yml
2 jarの外にある application.yml
3 jarの中にある application-{profile}.yml
4 jarの中にある application.yml

覚え方は「外から渡したものほど強い」「プロファイル専用のものほど強い」の2つです。同じ場所に application.properties と application.yml の両方があると、.properties が優先されます。公式ドキュメントでは、どちらか一方の形式に揃えることが推奨されています。

環境変数で設定を上書きする:名前の付け方

コンテナやクラウドでは、設定ファイルは共通のまま、環境ごとに違う値を環境変数で渡すのが一般的です。多くのOSでは環境変数の名前にドットを使えないため、Spring Bootは次のルールで対応づけます(公式ドキュメント「Binding From Environment Variables」)。

ルール 例
ドット(.)をアンダースコア(_)に spring.datasource.url → SPRING_DATASOURCE_URL
ハイフン(-)は取り除く spring.main.log-startup-info → SPRING_MAIN_LOGSTARTUPINFO
すべて大文字に app.page-size → APP_PAGESIZE
リストの番号はアンダースコアで囲む my.service[0].other → MY_SERVICE_0_OTHER

ハイフンは「アンダースコアに置き換える」のではなく「取り除く」のが公式の規則です。迷ったら、公式の規則どおりの名前にしておくと確実です。また、Mapにバインドする場合、環境変数の名前は小文字に変換されてからキーになるため、Mapのキーは常に小文字になります(値は変換されません)。

# docker compose での例
services:
  app:
    image: order-api:latest
    environment:
      SPRING_PROFILES_ACTIVE: prod
      SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/orders
      APP_PAGESIZE: "100"
      DB_PASSWORD: ${DB_PASSWORD}

@ConfigurationPropertiesで設定をまとめて受け取る

独自の設定値は、@Value で1つずつ受け取るより、@ConfigurationProperties でクラスにまとめて受け取る方が、型のチェックや入力チェックができて安全です。

app:
  page-size: 20
  notification:
    enabled: true
    from: noreply@example.com
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.validation.annotation.Validated;

@Validated
@ConfigurationProperties(prefix = "app")
public record AppProperties(
        @Min(1) @Max(200) @DefaultValue("20") int pageSize,
        Notification notification) {

    public record Notification(boolean enabled, String from) {}
}
@SpringBootApplication
@ConfigurationPropertiesScan      // @ConfigurationProperties のクラスを探して登録する
public class OrderApiApplication { ... }
比べる点 @ConfigurationProperties @Value("${...}")
名前のゆれへの対応(relaxed binding) page-size・pageSize・APP_PAGESIZE のどれでも受け取れる 名前を正確に合わせる必要がある
型の変換・入力チェック できる(@Validated) 限定的
まとめて扱う クラス単位で扱える 1つずつ

@Value を使う場合は、${app.page-size} のように、小文字とハイフンの正式な形で書きます。公式ドキュメントでは、こう書くと @ConfigurationProperties と同じ規則で値を探せる、と説明されています。

パスワードなど秘密の値の扱い

パスワードやAPIキーは、application-prod.yml に直接書いてGitに入れないようにします。一度リポジトリに入ると、履歴から消すのは大変です。

方法 書き方 向いている場面
環境変数から受け取る password: ${DB_PASSWORD} 基本の形。コンテナ・クラウド
マウントされたファイルから読む spring.config.import: optional:configtree:/etc/secrets/ Kubernetesのシークレットなど
外部の秘密情報の管理サービス 各クラウドの管理サービスや、それと連携するライブラリ 秘密の値を一元管理したいとき
手元の開発用ファイル application-local.yml を .gitignore に入れる 開発者ごとの値

${DB_PASSWORD} は、プレースホルダー(別の設定値や環境変数を差し込む書き方)です。${DB_PASSWORD:} と書くと、値がないときは空文字になります。本番では、値がないときに起動が失敗する方が、気づきやすく安全です。

configtree は、/etc/secrets/db/password のようなファイルの中身を、db.password という設定値として読み込む仕組みです。また、Spring Boot 3.0以降、Actuatorの /actuator/env などのエンドポイントは、標準で設定値を伏せ字で表示します(management.endpoint.env.show-values の既定が never)。表示するように変えるときは、秘密の値が見えてしまわないか確認します。

@ProfileでBeanを切り替える

設定の値だけでなく、使うクラスそのものを環境ごとに切り替えるには @Profile を使います。

public interface MailSender {
    void send(String to, String body);
}

@Component
@Profile("prod")
class SmtpMailSender implements MailSender { ... }       // 本番:実際に送る

@Component
@Profile("!prod")
class LoggingMailSender implements MailSender { ... }    // それ以外:ログに出すだけ
書き方 意味
@Profile("prod") prodが有効なときだけ
@Profile("!prod") prod以外のとき
@Profile({"dev", "local"}) devまたはlocalのとき
@Profile("prod & cloud") 両方が有効なとき

コードの中で spring.profiles.active の文字列を読んで if で分けるのは避けます。複数のプロファイルを指定したときに正しく判定できません。どうしてもコードで判定する場合は、Environment#acceptsProfiles(Profiles.of("prod")) を使います。

テストでのプロファイル指定

@SpringBootTest
@ActiveProfiles("test")
class OrderServiceIntegrationTest {
    // src/test/resources/application-test.yml の設定が使われる
}
方法 使いどころ
@ActiveProfiles("test") テスト用のプロファイル(application-test.yml)を有効にする
@SpringBootTest(properties = "app.page-size=5") そのテストだけで値を変える
@TestPropertySource(properties = ...) 同上。優先順位は最も高い
@DynamicPropertySource テスト用コンテナのポートなど、実行時に決まる値を渡す

テスト用の設定は src/test/resources に置き、本番用の設定ファイルを直接読むテストにしないと、本番の設定を変えたときにテストが意図せず影響を受けるのを防げます。

Spring Boot 4系での注意点

項目 内容
前提となるバージョン Spring Boot 4系は、Java 17以上・Spring Framework 7が前提
プロファイル名のチェック Spring Boot 3.5以降、プロファイル名に使える文字がチェックされる。現在の公式ドキュメントでは、英数字と - _ . + @、先頭と末尾は英数字。無効にするには spring.profiles.validate: false
テストのモック @MockBean・@SpyBean が削除された。@MockitoBean・@MockitoSpyBean に置き換える
設定項目の名前の変更 名前が変わった・なくなった設定項目は、spring-boot-properties-migrator を一時的に依存関係に入れると、起動時に教えてくれる

3系から4系へ上げるときは、まず spring-boot-properties-migrator で設定ファイルの古い項目を洗い出すと、プロファイルごとの設定の漏れにも気づきやすくなります。

よくある失敗と直し方

症状 よくある原因 直し方
プロファイル専用の設定が反映されない ファイル名のつづり違い(application-prd.yml など) 起動ログの有効なプロファイル名と、ファイル名を見比べる
本番でローカルの設定で動いた application.yml に spring.profiles.active: local spring.profiles.default に変える
起動時にエラーになる on-profile のドキュメントや、プロファイル専用ファイルの中に spring.profiles.active を書いた 共通の application.yml か、起動時の指定に移す
環境変数で上書きできない 名前の変換の誤り(ドットの置き換え漏れ、リストの番号の書き方など) 公式の規則どおり APP_PAGESIZE・MY_SERVICE_0_OTHER の形にする
ymlを直したのに値が変わらない 同じ場所に .properties もある、または環境変数・起動引数で上書きされている 優先順位の表を上から確認する
YAMLの設定が効かない インデントのずれ、タブ文字 スペースでインデントし、階層を確認する

よくある質問

Q. application.yml と application.properties は、どちらを使えばよいですか? A. 機能は同じです。階層が深い設定はYAMLの方が読みやすく、1行ずつ検索しやすいのはpropertiesです。同じ場所に両方あるとpropertiesが優先されるため、どちらか一方に揃えます。

Q. 環境ごとの設定を、jarの中に全部入れてもよいですか? A. URLやログのレベルのような秘密でない値は、jarの中の application-{profile}.yml に入れて問題ありません。パスワードなど秘密の値は、環境変数やシークレットの仕組みで外から渡すようにします。外から渡した値は、jarの中の設定より優先されます。

Q. プロファイルはいくつ作るのがよいですか? A. 実際の環境(ローカル・検証・本番など)に合わせた最小限にします。機能のオン・オフのような細かい切り替えまでプロファイルにすると組み合わせが増えるため、機能の切り替えは app.feature.xxx.enabled のような設定値で行い、プロファイルは環境の違いに使うと整理しやすくなります。

Q. SPRING_PROFILES_ACTIVE と --spring.profiles.active の両方を指定したら、どちらが使われますか? A. 優先順位の表のとおり、コマンドライン引数の方が優先されます。

まとめ

  • 共通の設定は application.yml、環境ごとの違いだけを application-{profile}.yml に書く
  • 指定は --spring.profiles.active・SPRING_PROFILES_ACTIVE。既定は active ではなく spring.profiles.default で決める
  • 1ファイルにまとめるなら --- と spring.config.activate.on-profile(spring.profiles: prod は古い書き方)
  • 優先順位は 「外から渡したものほど強い」「プロファイル専用ほど強い」。コマンドライン引数 > 環境変数 > 設定ファイル
  • 環境変数の名前は ドットをアンダースコアに、ハイフンは取り除き、大文字に
  • 独自の設定は @ConfigurationProperties、秘密の値はファイルに書かず外から渡す
  • Beanの切り替えは @Profile、テストは @ActiveProfiles。有効なプロファイルは起動ログで確認する

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Spring Bootプロファイル切り替え|application.ymlと優先順位」

株式会社RJCでは、環境ごとの設定を安全に扱うための工夫を、プロジェクトの中で仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?