Profileとは何か
Spring Bootの Profile は、「今どの環境で動いているか(開発・検証・本番など)」を表すスイッチです。
このスイッチに応じて、Beanの有効/無効や設定値(DB接続先、ログレベル、外部APIのURLなど)を切り替えられます。
たとえば次のような切り替えを安全に行えます。
- 開発ではH2、本番ではPostgreSQL
- 開発では詳細ログ、本番ではINFO中心
- 開発ではモックの外部API、本番では実API
「設定を手で書き換えてデプロイ」みたいな事故を減らせるのが、Profileの大きな価値です。
Profileで何が切り替わるのか
Profileで主に切り替える対象は次の2つです。
- 設定ファイル(application.yml / properties)の値
- SpringのBean定義(@Bean / @Component など)の有効化
設定ファイルをProfileごとに分ける基本
一番よく使うのが、application-<profile>.yml(または.properties)での分割です。
たとえば、以下のように分割することができます。
application.yml(共通)application-dev.yml(開発用)application-prod.yml(本番用)application-test.yml(テスト用)
application.yml(共通)
spring:
application:
name: demo
logging:
level:
root: INFO
application-dev.yml(開発)
spring:
datasource:
url: jdbc:h2:mem:testdb
jpa:
hibernate:
ddl-auto: create-drop
logging:
level:
root: DEBUG
application-prod.yml(本番)
spring:
datasource:
url: jdbc:postgresql://db.prod.example.com:5432/app
jpa:
hibernate:
ddl-auto: validate
logging:
level:
root: INFO
application-test.yml(テスト)
spring:
datasource:
url: jdbc:h2:mem:testdb
jpa:
hibernate:
ddl-auto: create-drop
logging:
level:
root: WARN
ポイントは「共通はapplication.ymlに置き、環境差分だけをprofile側に書く」ことです。
差分が見やすくなり、設定の重複も減ります。
Profileを有効化する方法
Profileの有効化(どれを使うか)はいくつか方法があります。よく使う順に紹介します。
起動引数で指定する
ローカル実行や一時的な切り替えで便利です。
java -jar app.jar --spring.profiles.active=dev
JVMのシステムプロパティ(-D)で指定する
-Dspring.profiles.active=... のように、JVMのシステムプロパティで渡す方法もあります。java コマンドの直後、jarファイル名より前に書くのがポイントです。jarファイル名の後ろに書くとアプリの引数として扱われ、Profileの指定にはなりません。
java -Dspring.profiles.active=prod -jar app.jar
起動引数(--spring.profiles.active)と同じキーを指定しているので、効き方はほぼ同じです。両方を書いた場合は起動引数の方が優先されます。
IntelliJ IDEAの実行構成で「VM options」に書くときや、JAVA_TOOL_OPTIONS のようにJVMオプションをまとめて渡す仕組みがある環境では、この -D 形式の方が扱いやすいです。
環境変数で指定する
DockerやKubernetesなど、コンテナ運用でよく使います。
export SPRING_PROFILES_ACTIVE=prod
KubernetesのDeploymentから環境変数やSecretを渡す具体的なManifestの書き方は Spring BootアプリをKubernetesにデプロイする方法 で解説しています。
application.ymlで指定する(おすすめしない場面もある)
spring:
profiles:
active: dev
これは「常にdevで動く」状態になりやすいので注意です。
CI/CDや本番デプロイが絡むなら、環境変数やデプロイ設定側で制御する方が安全です。
Gradleでテスト実行時だけ常にtest Profileを有効にする
「./gradlew test でテストを走らせるときだけ、毎回 test Profileにしたい」なら、Gradleのtestタスクに システムプロパティ として渡すのが簡単です。
Groovy DSL(build.gradle)
tasks.named('test') {
useJUnitPlatform()
systemProperty 'spring.profiles.active', 'test'
}
これで、Gradle経由でテストを実行する限り test Profileが常に有効になります。
環境変数で渡したい場合は次のようにも書けます。
tasks.named('test') {
useJUnitPlatform()
environment 'SPRING_PROFILES_ACTIVE', 'test'
}
Kotlin DSL(build.gradle.kts)
tasks.test {
useJUnitPlatform()
systemProperty("spring.profiles.active", "test")
}
注意点
- この設定は「Gradleの
testタスク」にだけ効きます。bootRunなどには影響しません。 - IDEの「JUnitを直接実行(Gradleを使わない実行設定)」だと、この設定が反映されないことがあります。その場合はIDE側を「Gradleでテスト実行」に切り替えるか、テストクラスに
@ActiveProfiles("test")を付ける方法も検討してください。
テストクラスで@ActiveProfilesを使ってtest Profileを指定する
Gradle側の設定に頼らず、テストコード自身で「このテストはtest Profileで動かす」と宣言したいなら、@ActiveProfiles を使います。@SpringBootTest と組み合わせるのが定番です。
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles("test")
class UserServiceTest {
}
これで、このテストクラスを実行するときは application-test.yml が読み込まれます。IDEから直接実行しても、Gradleから実行しても同じ結果になるのが嬉しいところです。
@ActiveProfiles は spring.profiles.active より優先されます。Gradleのtestタスクで別のProfileを渡していても、アノテーション側が勝つと覚えておきましょう。
テストクラスごとに書くのが面倒なら、@SpringBootTest と @ActiveProfiles("test") を付けた抽象クラスを1つ用意して、各テストクラスはそれを継承するだけにしておくと楽です。
なお、特定のテストでだけ一部の値を上書きしたいときは、Profileを増やすより @TestPropertySource や @SpringBootTest(properties = "...") で十分な場面も多いです。「環境全体の切り替え」はProfile、「このテストだけの微調整」はプロパティ上書き、と使い分けると設定ファイルが散らかりません。
ProfileでBeanを切り替える
設定値だけでなく、BeanそのものもProfileで出し分けできます。
@Profileでクラス単位に切り替え
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Profile("dev")
@Component
public class DevOnlyInitializer {
}
このBeanはdev Profileのときだけ登録されます。
「開発環境だけ起動時に初期データを投入したい」ような処理は、この形のクラスで CommandLineRunner を実装するのが定番です。起動時処理の書き方は Spring BootのCommandLineRunner・ApplicationRunnerで起動時処理を実行する方法 で解説しています。
@Configuration + @Beanにも使える
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
public class ClientConfig {
@Profile("dev")
@Bean
public ApiClient mockClient() {
return new ApiClient("http://localhost:8081");
}
@Profile("prod")
@Bean
public ApiClient realClient() {
return new ApiClient("https://api.example.com");
}
}
これで、外部APIクライアントを環境で差し替える、といった構成が作れます。
1つだけじゃないProfileの指定
Profileは複数同時に有効化できます。
--spring.profiles.active=dev,feature-x
この場合、dev と feature-x の両方が有効になります。
「環境」と「機能フラグ」を分ける設計にすると、切り替えがスムーズです。
groupでまとめて有効化する
Profileが増えてくると「devを選ぶと、dev用+ローカル用も一緒にONにしたい」みたいな要望が出ます。
そのときは Profile Group が便利です。
spring:
profiles:
group:
dev:
- dev
- local
これで spring.profiles.active=dev とすると dev と local がまとめて有効になります。
1ファイルにまとめて書くマルチドキュメント形式
Spring Boot 2.4以降では、ファイルを分けずに1つの application.yml の中を --- で区切り、spring.config.activate.on-profile で「このブロックはどのProfileで有効か」を書く方法も使えます。
spring:
application:
name: demo
---
spring:
config:
activate:
on-profile: dev
datasource:
url: jdbc:h2:mem:testdb
---
spring:
config:
activate:
on-profile: prod
datasource:
url: jdbc:postgresql://db.prod.example.com:5432/app
最初のブロックは常に読み込まれ、on-profile 付きのブロックは該当Profileが有効なときだけ反映されます。設定が少ないうちは1ファイルで見通しがよく、増えてきたら application-<profile>.yml に切り出す、という進め方がおすすめです。
古い記事で見かける spring.profiles: dev という書き方はSpring Boot 2.4で非推奨になり、3系では起動時にエラーになります。新しく書くなら spring.config.activate.on-profile を使いましょう。
includeとdefaultも押さえておく
spring.profiles.include は「有効にしたProfileに加えて、これも常に有効にする」ための設定です。どの環境でも使う common のようなProfileを足したいときに、spring.profiles.include: common のように書きます。
spring.profiles.default は「何もProfileを指定しなかったときに使うProfile」です。Spring Bootの初期値は default という名前で、application-default.yml があればそれが読まれます。
注意点として、spring.profiles.include は on-profile 付きのブロックや application-<profile>.yml の中には書けません(起動時にエラーになります)。spring.profiles.group もProfileの構成そのものを決める設定なので、共通部分(最初のブロック)か application.yml 本体に置くのが安全です。
よくある落とし穴と対策
本番にdev設定で起動してしまう
原因はだいたい次のどれかです。
application.ymlにspring.profiles.active=devを書いている- デプロイ環境で環境変数が設定されていない
- 起動スクリプトが古い
対策としては、「本番は必ずデプロイ設定でSPRING_PROFILES_ACTIVE=prodを明示する」を強くおすすめします。
設定の優先順位がわからなくなる
同じキーが複数箇所にあると混乱します。基本イメージはこうです。
- 「より外側(環境変数や起動引数)」が強い
- 「より具体(profile側)」が強いことが多い
困ったら、起動ログにどのProfileが有効かが出るので、まずそこを確認すると解決が早いです。
application-xxx.ymlが読み込まれていない
Profile名のタイプミスが多いです。
application-prod.ymlを用意したのに--spring.profiles.active=productionで起動している
→ ファイル名とProfile名は一致させる必要があります
開発と運用でのおすすめ構成
迷ったらこの形が扱いやすいです。
application.yml:共通設定application-dev.yml:開発環境の差分application-prod.yml:本番環境の差分application-test.yml:テスト環境の差分- 起動時に
SPRING_PROFILES_ACTIVEを必ず明示(特に本番)
「本番にだけ置くべき値(パスワード、APIキーなど)」は、設定ファイルに直書きせず、環境変数やシークレット管理(Kubernetes Secretなど)で渡すのが安全です。
どうしても設定ファイル側に置きたい値がある場合は、暗号化した文字列だけをコミットする方法もあります。手順は Spring BootでJasyptを使って設定ファイルの機密情報を暗号化する方法 で解説しています。
優先順位で混乱しないための整理
同じキーを複数箇所に書くと、どの値が採用されたか分からなくなりやすいです。
実務では次の優先順(強い順)を覚えておくとトラブルシュートが速くなります。
- 起動引数(
--spring.profiles.active=...) - 環境変数(
SPRING_PROFILES_ACTIVE) application-<profile>.ymlapplication.yml
運用方針として「本番は環境変数で明示、設定ファイルは差分定義に集中」と決めると事故を減らせます。
チーム開発向けの運用ルール
Profile運用が崩れると、環境差分バグが頻発します。次のルールをおすすめします。
application.ymlにspring.profiles.activeを固定で書かない- PR時に「どのProfileで検証したか」を記録する
- 新しい設定キーを追加したら
dev/prod/testの差分有無を必ず確認する - シークレットはリポジトリに置かず、環境側のSecret管理へ寄せる
Profileは便利ですが、運用ルールとセットで初めて安全に機能します。
まとめ
Spring Bootの Profile を使うと、環境ごとの設定やBeanを安全に切り替えられます。
application-<profile>.ymlで設定値を分ける--spring.profiles.activeやSPRING_PROFILES_ACTIVEで有効化する@ProfileでBeanを環境ごとに差し替えられる- Gradleの
testタスクでspring.profiles.active=testを渡すと、テスト実行時だけProfileを固定できる - 本番は「必ず明示的にprodを指定」して事故を防ぐ
Profileを活用して、安全に環境を分離してみてください!