404 Not Found

404 Not Found


nginx

設定管理

設定管理は開発と本番の橋渡しです。1つのコードベース, 複数の設定, 環境の切り替えは1行のパラメータで済みます。

1. 学ぶ内容


2. 運用エンジニアの実話

(1) ペインポイント:設定があちこちに散在

BobはOrderFlowの運用エンジニアで, デプロイのたびに「発掘作業」のような思いをしていました。データベースのパスワードがコードにハードコードされ, テスト環境と本番環境の設定が1つのファイルに混在しています。誰かが本番データベースのパスワードを変更したがコードの更新を忘れ, システムが2時間ダウンしました。CharlieにSLAについて問い詰められたとき, Bobは「設定管理がめちゃくちゃなんです」とため息交じりに説明するしかありませんでした。

(2) Spring Boot Profilesによる解決策

Spring BootはProfileメカニズムを使って複数環境の設定を分離します。

YAML
# application-dev.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/orderflow_dev
    username: dev_user
    password: dev_pass
YAML
# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://prod-db.internal:3306/orderflow
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}

(3) 成果

BobがProfileと環境変数を使ってリファクタリングした後, 開発環境はdevを, 本番環境はprodを使用するようになりました。機密情報はコードリポジトリに含まれなくなり, デプロイの切り替えは--spring.profiles.active=prodだけで済み, 設定エラーによるダウンタイムはゼロになりました。


3. Profile:マルチ環境設定

(1) Profileファイルの命名規則

Spring Bootはapplication-{profile}.ymlの命名規則に従ってProfile設定を読み込みます。

TEXT
src/main/resources/
├── application.yml            # 共通設定 (共有)
├── application-dev.yml        # 開発Profile
├── application-prod.yml       # 本番Profile
└── application-test.yml       # テストProfile
100%
graph TD
    A["application.yml<br/>共通設定"] --> B["application-dev.yml<br/>開発環境の上書き"]
    A --> C["application-prod.yml<br/>本番環境の上書き"]
    A --> D["application-test.yml<br/>テスト環境の上書き"]
    B --> E["マージされた設定<br/>Profile=dev"]
    C --> F["マージされた設定<br/>Profile=prod"]
有効化方法 コマンド 優先度
設定ファイル application.ymlにspring.profiles.active=dev 最低
環境変数 SPRING_PROFILES_ACTIVE=dev
コマンドライン引数 --spring.profiles.active=dev 最高

(1) ▶ サンプル:Profile

YAML
# application.yml (共有)
spring:
  application:
    name: orderflow-service
  profiles:
    active: dev

server:
  port: 8080

出力:

TEXT
設定が正常に適用されました
YAML
# application-dev.yml
spring:
  datasource:
    url: jdbc:h2:mem:orderflow_dev
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true

logging:
  level:
    com.orderflow: DEBUG
YAML
# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://${DB_HOST:localhost}:3306/orderflow
    username: ${DB_USERNAME}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false

logging:
  level:
    com.orderflow: WARN

4. @Valueと@ConfigurationPropertiesの比較

(1) 2つのインジェクション方法

(1) ▶ サンプル:@Valueインジェクション

JAVA
@RestController
public class OrderController {

    @Value("${orderflow.max-items-per-order:100}")
    private int maxItemsPerOrder;

    @Value("${orderflow.default-currency:USD}")
    private String defaultCurrency;

    @GetMapping("/api/config/check")
    public Map<String, Object> checkConfig() {
        return Map.of(
            "maxItemsPerOrder", maxItemsPerOrder,
            "defaultCurrency", defaultCurrency
        );
    }
}

出力:

TEXT
// 実行成功

(2) ▶ サンプル:@ConfigurationPropertiesによるタイプセーフバインディング

JAVA
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
    int maxItemsPerOrder,
    String defaultCurrency,
    Duration orderTimeout,
    ShippingConfig shipping
) {
    public record ShippingConfig(
        boolean freeShippingEnabled,
        BigDecimal freeShippingThreshold
    ) {}
}

// メインクラスまたは設定クラスで有効化
@EnableConfigurationProperties(OrderFlowProperties.class)

出力:

TEXT
// 実行成功
項目 @Value @ConfigurationProperties
型安全性 弱い (主にString) 強い (自動型変換)
ネストされたオブジェクト 非サポート サポート
コレクションバインディング 非サポート List/Mapをサポート
検証 なし @Validatedと組み合わせ
IDEサポート ヒントなし 自動補完 (メタデータ)
使用場面 少数の単純な値 構造化されたビジネス設定

(3) ▶ サンプル:YAMLとConfigurationPropertiesのマッピング

YAML
orderflow:
  max-items-per-order: 50
  default-currency: USD
  order-timeout: 30m
  shipping:
    free-shipping-enabled: true
    free-shipping-threshold: 49.99

出力:

TEXT
設定が反映されました。
JAVA
// アクセス例
@Component
public class OrderService {
    private final OrderFlowProperties props;

    public OrderService(OrderFlowProperties props) {
        this.props = props;
    }

    public boolean isFreeShipping(BigDecimal orderTotal) {
        return props.shipping().freeShippingEnabled()
            && orderTotal.compareTo(props.shipping().freeShippingThreshold()) >= 0;
    }
}

5. 設定優先度の階層

(1) 高い順の優先度

100%
graph TD
    A["1. コマンドライン引数<br/>--server.port=9090"] --> B["2. JNDI属性"]
    B --> C["3. Javaシステムプロパティ<br/>-Dserver.port=9090"]
    C --> D["4. OS環境変数<br/>SERVER_PORT=9090"]
    D --> E["5. application-{profile}.yml<br/>Profile固有"]
    E --> F["6. application.yml<br/>デフォルト設定"]
    F --> G["7. デフォルト値<br/>コード内のアノテーション"]
優先度 ソース
1 (最高) コマンドライン引数 --server.port=9090
2 JNDIプロパティ java:comp/env/...
3 JVMシステムプロパティ -Dserver.port=9090
4 OS環境変数 SERVER_PORT=9090
5 Profile application-prod.yml
6 デフォルト設定ファイル application.yml
7 (最低) デフォルト値 @Value("${x:default}")
💡 ヒント: 本番環境では, 機密設定を環境変数またはコマンドライン引数で上書きすることを推奨します。パスワードを設定ファイルに含めないでください。


6. ネストされた設定とコレクションバインディング

(1) リストとマップのバインディング

(1) ▶ サンプル:リストとマップの設定

YAML
orderflow:
  supported-currencies:
    - USD
    - EUR
    - GBP
  payment-gateways:
    stripe:
      api-key: ${STRIPE_API_KEY}
      webhook-secret: ${STRIPE_WEBHOOK_SECRET}
    paypal:
      client-id: ${PAYPAL_CLIENT_ID}
      secret: ${PAYPAL_SECRET}

出力:

TEXT
CI/CDパイプライン設定が読み込まれました
パイプラインステータス:合格
テスト:12合格, 0失敗
JAVA
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
    List<String> supportedCurrencies,
    Map<String, GatewayConfig> paymentGateways
) {
    public record GatewayConfig(
        String apiKey,
        String webhookSecret,
        String clientId,
        String secret
    ) {}
}

7. 総合サンプル:OrderFlowの完全な設定システム

JAVA
// OrderFlowProperties.java
package com.orderflow.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.List;
import java.util.Map;

@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
    int maxItemsPerOrder,
    String defaultCurrency,
    Duration orderTimeout,
    ShippingConfig shipping,
    List<String> supportedCurrencies,
    Map<String, GatewayConfig> paymentGateways
) {
    public record ShippingConfig(
        boolean freeShippingEnabled,
        BigDecimal freeShippingThreshold
    ) {}

    public record GatewayConfig(
        String apiKey,
        String webhookSecret,
        String clientId,
        String secret
    ) {}
}

// AppConfig.java
package com.orderflow.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(OrderFlowProperties.class)
public class AppConfig {}
YAML
# application.yml
spring:
  application:
    name: orderflow-service
  profiles:
    active: dev

orderflow:
  max-items-per-order: 50
  default-currency: USD
  order-timeout: 30m
  supported-currencies:
    - USD
    - EUR
    - GBP
  shipping:
    free-shipping-enabled: true
    free-shipping-threshold: 49.99
  payment-gateways:
    stripe:
      api-key: ${STRIPE_API_KEY:dev-key}
      webhook-secret: ${STRIPE_WEBHOOK_SECRET:dev-secret}

❓ よくある質問

Q @ConfigurationPropertiesと@Valueはどちらを選ぶべきですか?
A 構造化された設定には@ConfigurationPropertiesを使用してください (型安全性, ネスト, IDEサポート)。少数の単純な値には@Valueを使用します。1つのプロジェクトで混在しすぎないようにしてください。
Q 機密情報がコードリポジトリに漏れるのを防ぐにはどうすればよいですか?
A 1)設定ファイルで${ENV_VAR}プレースホルダーを使って環境変数を参照する;2).gitignoreで機密設定ファイルを除外する;3)本番環境ではK8s SecretsやVaultでシークレットを管理する。
Q Profile設定とデフォルト設定はどのようにマージされますか?
A Spring Bootはまずデフォルト設定を読み込み, 次にProfile設定で一致するプロパティを上書きします。異なるプロパティは補完し合い, 一致するプロパティはProfileが優先されます。
Q Properties形式でリストを書くにはどうすればよいですか?
A orderflow.supported-currencies[0]=USD, orderflow.supported-currencies[1]=EUR。リストのインデックスは0から始まります。
Q コードで動的にProfileを切り替えるにはどうすればよいですか?
A コードでの動的なProfile切り替えは推奨されません。Profileは起動時に決定されるべきです。実行時に動的に設定を切り替える必要がある場合は, Spring Cloud Configやカスタム設定リフレッシュメカニズムを使用してください。
Q recordConfigurationPropertiesとして使用する制限は何ですか?
A recordは不変であり, 読み取り専用の設定に適しています。Spring Boot 3.xはrecordバインディングをサポートしています。ただし, JSR-380検証のために@Validatedと組み合わせることはできません (recordには引数なしコンストラクタがないため), クラスを使用する必要があります。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度 ⭐):OrderFlowに2つのProfileを設定してください。1つはdev, 1つはprodです。devはH2インメモリデータベース, prodはMySQLを使用し, コマンドライン引数で切り替えてください。

  2. 応用問題 (難易度 ⭐⭐):@ConfigurationPropertiesを使ってPaymentGatewayPropertiesを作成し, StripeとPayPalのAPIキー設定を含めてください。キーの値は環境変数からインジェクションしてください。

  3. チャレンジ問題 (難易度 ⭐⭐⭐):カスタムPropertySourceを実装してリモート設定センターから設定を読み込んでください (モックHTTPエンドポイントを使用可)。Spring BootのEnvironment抽象化の設計意図について考察してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%