Contents
- 1 1. マイクロサービスとは? Spring が提供する主な支援機能
- 2 2. 開発環境の構築 – JDK 21・IDE・Spring Initializr
- 3 3. 必要なスターターと依存関係 – Maven と Gradle の実装例
- 4 4. 基本サービスの実装 – Eureka、Config Server、REST API、テスト
- 5 5. サービス間通信 – Feign と Function‑style Spring Cloud Stream
- 6 6. Docker コンテナ化とローカルマルチサービス環境
- 7 7. CI/CD パイプライン – GitHub Actions の実装例
- 8 8. 全体まとめ & 次のステップ
1. マイクロサービスとは? Spring が提供する主な支援機能
1‑1. 基本概念(概要)
| 項目 | 従来のモノリシック方式 | 現代のマイクロサービス |
|---|---|---|
| デプロイ単位 | アプリ全体を一括デプロイ | サービスごとに独立した JAR/コンテナ |
| スケーリング | プロセス数増加で対応(リソース浪費) | 必要なサービスだけ水平スケール |
| 障害影響範囲 | 1つの障害が全体を停止させやすい | サービス間は疎結合なので局所的に切り離し可能 |
参考:Spring Cloud の公式ガイド「Microservices with Spring Cloud」
1‑2. Spring が提供する支援機能(2025 年 12 月リリース)
| カテゴリ | 主なモジュール | 代表的な機能 |
|---|---|---|
| DI / コンポーネントスキャン | Spring Framework | @Component, @Autowired による疎結合実装 |
| サービスディスカバリ | Spring Cloud Netflix Eureka | クライアントは spring-cloud-starter-netflix-eureka-client を追加するだけで自動登録/検索 |
| 外部設定管理 | Spring Cloud Config Server | Git・SVN・ローカルファイルをバックエンドにした集中設定 |
| 分散トレーシング & メトリクス | Spring Boot Actuator + Micrometer | /actuator/prometheus で Prometheus にメトリクス公開 |
| 同期呼び出し | Spring Cloud OpenFeign | @FeignClient だけで HTTP クライアントが生成 |
| 非同期メッセージング | Spring Cloud Stream (Function‑style) | Supplier/Consumer/Function ビーンで RabbitMQ/Kafka と連携 |
根拠:Spring Boot 3.2 リリースノート(Release Notes 3.2.0)・Spring Cloud 2023.0.1 BOM(BOM Docs)
2. 開発環境の構築 – JDK 21・IDE・Spring Initializr
2‑1. JDK 21 のインストールと確認
| OS | インストール手順 |
|---|---|
| macOS | brew install openjdk@21 sudo ln -sfn $(brew --prefix)/opt/openjdk@21/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-21.jdk |
| Windows | choco install temurin21 |
インストール後は必ず次のコマンドでバージョンを確認:
|
1 2 3 |
java -version # 出力例: openjdk version "21" 2023-09-19 LTS |
公式:OpenJDK 21 ダウンロードページ(https://jdk.java.net/21/)
2‑2. IDE の設定ポイント
| IDE | 必要プラグイン・設定 |
|---|---|
| IntelliJ IDEA Ultimate | Spring Boot, Lombok, Docker プラグインを有効化。File → Settings → Build, Execution, Deployment → Compiler で Target bytecode version を 21 に設定。 |
| VS Code | 拡張機能「Java Extension Pack」「Spring Boot Dashboard」必須。.vscode/settings.json に runtime 設定を追加:json { "java.configuration.runtimes": [{ "name": "JavaSE", "version": "21" }] } |
2‑3. Spring Initializr でプロジェクト作成
| 項目 | 推奨設定 |
|---|---|
| Project | Maven(Gradle でも可) |
| Language | Java |
| Spring Boot | 3.2.0(執筆時点の最新安定版) |
| Packaging | Jar |
| Java | 21 |
| Dependencies | Spring Web, Actuator, Eureka Discovery Client, Config Client, OpenFeign, Spring Cloud Stream (RabbitMQ) |
生成された pom.xml とディレクトリ構成は以下の通りです(抜粋):
|
1 2 3 4 5 6 7 |
src/ └─ main/ ├─ java/com/example/demo/DemoApplication.java └─ resources/ └─ application.yml pom.xml |
参考:Spring Initializr 公式サイト(https://start.spring.io/)
3. 必要なスターターと依存関係 – Maven と Gradle の実装例
3‑1. BOM 管理(Spring Cloud 2023.0.1)
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2023.0.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> |
3‑2. Maven (pom.xml) 完全例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
<properties> <java.version>21</java.version> <spring-boot.version>3.2.0</spring-boot.version> </properties> <dependencies> <!-- Web & Actuator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Eureka (Discovery) --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- Config Client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-client</artifactId> </dependency> <!-- OpenFeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- Spring Cloud Stream (RabbitMQ) – Function style --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rabbit</artifactId> </dependency> <!-- Testcontainers + JUnit5 --> <dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> </dependencies> |
3‑3. Gradle (Kotlin DSL) 完全例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
plugins { id("org.springframework.boot") version "3.2.0" id("io.spring.dependency-management") version "1.1.5" kotlin("jvm") version "1.9.22" } java { sourceCompatibility = JavaVersion.VERSION_21 } dependencyManagement { imports { mavenBom("org.springframework.cloud:spring-cloud-dependencies:2023.0.1") } } dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client") implementation("org.springframework.cloud:spring-cloud-config-client") implementation("org.springframework.cloud:spring-cloud-starter-openfeign") implementation("org.springframework.cloud:spring-cloud-stream-binder-rabbit") // Function style testImplementation("org.testcontainers:junit-jupiter") } |
注意:
@EnableEurekaServer/@EnableEurekaClientは Spring Cloud 2023.0 系列では不要です。spring-cloud-starter-netflix-eureka-serverをクラスパスに置くだけで自動的に有効になります(公式ドキュメント: Eureka Server)。
4. 基本サービスの実装 – Eureka、Config Server、REST API、テスト
4‑1. Eureka サーバー(サンプルコード)
pom.xml に追加
|
1 2 3 4 5 |
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> |
エントリポイント
|
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.example.eureka; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // @EnableEurekaServer は自動的に有効になるが、可視性のため残すことも可 @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } } |
application.yml
|
1 2 3 4 5 6 7 8 |
server: port: 8761 eureka: client: register-with-eureka: false # サーバー自身は登録しない fetch-registry: false |
公式リファレンス:Eureka Server の最新ガイド(https://docs.spring.io/spring-cloud/docs/current/reference/html/#spring-cloud-eureka-server)
4‑2. Config Server(Git バックエンド)
依存追加
|
1 2 3 4 5 |
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> |
エントリポイント
|
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.example.config; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } } |
application.yml(サーバ側)
|
1 2 3 4 5 6 7 8 9 10 11 |
server: port: 8888 spring: cloud: config: server: git: uri: https://github.com/your-org/microservice-config.git default-label: main # ブランチ名 |
クライアント側(bootstrap.yml)
|
1 2 3 4 5 6 7 8 |
spring: application: name: product-service cloud: config: uri: http://localhost:8888 fail-fast: true # 起動時に設定取得失敗したら即停止 |
公式リファレンス:Spring Cloud Config Server(https://docs.spring.io/spring-cloud-config/reference/html/)
4‑3. REST API の実装例(Product Service)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.example.product; import jakarta.persistence.*; import lombok.*; @Entity @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private java.math.BigDecimal price; } |
|
1 2 3 4 5 6 7 8 |
package com.example.product; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ProductRepository extends JpaRepository<Product, Long> {} |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.example.product; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.List; @Service @RequiredArgsConstructor public class ProductService { private final ProductRepository repo; public List<Product> findAll() { return repo.findAll(); } public Product get(Long id) { return repo.findById(id).orElseThrow(() -> new IllegalArgumentException("Not found")); } public Product save(Product p) { return repo.save(p); } public void delete(Long id) { repo.deleteById(id); } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package com.example.product; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/products") @RequiredArgsConstructor public class ProductController { private final ProductService service; @GetMapping public List<Product> list() { return service.findAll(); } @PostMapping public ResponseEntity<Product> create(@RequestBody @Valid Product p) { Product saved = service.save(p); return ResponseEntity.status(HttpStatus.CREATED).body(saved); } @GetMapping("/{id}") public Product get(@PathVariable Long id) { return service.get(id); } @PutMapping("/{id}") public Product update(@PathVariable Long id, @RequestBody @Valid Product p) { p.setId(id); return service.save(p); } @DeleteMapping("/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) public void delete(@PathVariable Long id) { service.delete(id); } } |
ポイント:
@Validatedや@Validによる入力チェックは必須です。Spring Boot 3.2 のデフォルトは Jakarta Validation (jakarta.validation) へ移行しています(Release Notes)。
4‑4. 統合テスト – Testcontainers + JUnit 5
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package com.example.product; import org.junit.jupiter.api.*; import org.springframework.boot.test.context.SpringBootTest; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.beans.factory.annotation.Autowired; import static org.assertj.core.api.Assertions.*; @SpringBootTest @Testcontainers class ProductServiceIntegrationTest { @Container static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15") .withDatabaseName("testdb") .withUsername("user") .withPassword("pass"); @DynamicPropertySource static void datasourceProps(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); } @Autowired private ProductService service; @Test void saveAndRetrieve() { Product p = new Product(null, "Notebook", java.math.BigDecimal.valueOf(2_500)); Product saved = service.save(p); assertThat(saved.getId()).isNotNull(); Product fetched = service.get(saved.getId()); assertThat(fetched.getName()).isEqualTo("Notebook"); } } |
根拠:Testcontainers 公式サイト(https://www.testcontainers.org/)と Spring Boot 3.2 のテストガイド。
5. サービス間通信 – Feign と Function‑style Spring Cloud Stream
5‑1. 同期呼び出し:OpenFeign(最新 API)
依存はすでに spring-cloud-starter-openfeign が入っている前提です。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.example.order; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; @FeignClient(name = "product-service") // Eureka からインスタンスを解決 public interface ProductClient { @GetMapping("/api/products/{id}") ProductDto getProduct(@PathVariable("id") Long id); } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.example.order; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class OrderService { private final ProductClient productClient; public Order create(Long productId, int qty) { ProductDto product = productClient.getProduct(productId); // ビジネスロジック(価格計算等)… return new Order(productId, qty, product.price().multiply(java.math.BigDecimal.valueOf(qty))); } } |
公式リファレンス:OpenFeign の最新ガイド(https://docs.spring.io/spring-cloud-openfeign/reference/html/)
5‑2. 非同期メッセージング:Spring Cloud Stream Function Model
※
@EnableBindingは Spring Cloud Stream 4.x 系列で非推奨です。
代わりに Function Bean とspring.cloud.function.definitionを使用します。
(1) ビーン定義(Producer)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.example.order; import org.springframework.context.annotation.Bean; import org.springframework.messaging.MessageChannel; import org.springframework.integration.channel.DirectChannel; import java.util.function.Supplier; import com.fasterxml.jackson.databind.ObjectMapper; @Configuration(proxyBeanMethods = false) public class OrderStreamConfig { @Bean public Supplier<Message<OrderCreatedEvent>> orderCreatedSupplier() { return () -> MessageBuilder.withPayload(new OrderCreatedEvent(/*...*/)).build(); } } |
(2) ビーン定義(Consumer)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.example.inventory; import org.springframework.context.annotation.Bean; import java.util.function.Consumer; import lombok.extern.slf4j.Slf4j; @Configuration(proxyBeanMethods = false) @Slf4j public class InventoryStreamConfig { @Bean public Consumer<OrderCreatedEvent> orderCreatedConsumer() { return event -> { log.info("受信した OrderCreated イベント: {}", event); // 在庫減算ロジック… }; } } |
(3) application.yml でバインディング設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
spring: cloud: function: definition: orderCreatedSupplier;orderCreatedConsumer # セミコロン区切りで複数定義可 stream: bindings: orderCreatedSupplier-out-0: destination: orders producer: required-groups: order-service orderCreatedConsumer-in-0: destination: orders group: inventory-service |
公式ドキュメント:Spring Cloud Stream Function モデル(https://docs.spring.io/spring-cloud-stream/reference/html/function.html)
6. Docker コンテナ化とローカルマルチサービス環境
6‑1. 共通ベースイメージ(マルチステージビルド)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# ---------- Build stage ---------- FROM eclipse-temurin:21-jdk-alpine AS build WORKDIR /app COPY gradlew . COPY gradle ./gradle COPY build.gradle.kts settings.gradle.kts ./ RUN ./gradlew --no-daemon dependencies # 依存解決だけでキャッシュ活用 COPY src ./src RUN ./gradlew bootJar --no-daemon # ---------- Runtime stage ---------- FROM eclipse-temurin:21-jre-alpine VOLUME /tmp COPY --from=build /app/build/libs/*.jar app.jar ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] |
ポイント:
--no-daemonは CI 環境でのビルド速度向上に必須です(Gradle 公式ガイド)。
6‑2. docker-compose.yml 全体構成(抜粋)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
version: "3.9" services: eureka: build: ./eureka-server ports: ["8761:8761"] environment: - SPRING_PROFILES_ACTIVE=default config: build: ./config-server ports: ["8888:8888"] environment: - SPRING_PROFILES_ACTIVE=native # Git が不要な場合はローカルファイルで代用可 product-service: build: ./product-service depends_on: [eureka, config] environment: - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka:8761/eureka/ - SPRING_CLOUD_CONFIG_URI=http://config:8888 ports: ["8081:8080"] order-service: build: ./order-service depends_on: [eureka, config] environment: - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka:8761/eureka/ - SPRING_CLOUD_CONFIG_URI=http://config:8888 ports: ["8082:8080"] prometheus: image: prom/prometheus:v2.53 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: ["9090:9090"] grafana: image: grafana/grafana-oss:10.4 ports: ["3000:3000"] |
起動コマンド
|
1 2 |
docker compose up --build -d # バックグラウンドで起動 |
公式リファレンス:Docker Compose V2 ドキュメント(https://docs.docker.com/compose/)
6‑3. Actuator + Prometheus 設定例
application.yml(任意のマイクロサービス共通)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
management: endpoints: web: exposure: include: health,info,prometheus # 必要なエンドポイントだけ公開 metrics: export: prometheus: enabled: true dependencies: implementation "io.micrometer:micrometer-registry-prometheus" |
Prometheus の prometheus.yml(ローカル構成)
|
1 2 3 4 5 6 7 8 9 10 11 |
global: scrape_interval: 15s scrape_configs: - job_name: 'spring-boot' metrics_path: '/actuator/prometheus' static_configs: - targets: - product-service:8080 - order-service:8080 |
Grafana の公式ダッシュボード ID 6756(Spring Boot)をインポートすれば、CPU・JVM メモリ・HTTP レイテンシが即座に可視化できます。
参考:Micrometer 公式ドキュメント(https://micrometer.io/docs/registry/prometheus)
7. CI/CD パイプライン – GitHub Actions の実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
name: CI / CD on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build-test: runs-on: ubuntu-latest services: postgres: image: postgres:15 env: POSTGRES_DB: testdb POSTGRES_USER: user POSTGRES_PASSWORD: pass ports: ["5432:5432"] options: >- --health-cmd "pg_isready -U user" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v3 - name: Set up JDK 21 uses: actions/setup-java@v3 with: java-version: '21' distribution: temurin cache: maven # Maven 用キャッシュ - name: Build & Test (Maven) run: mvn -B clean verify - name: Build Docker image (product-service) run: | docker build -t ghcr.io/${{ github.repository }}/product-service:${{ github.sha }} ./product-service - name: Log in to GHCR uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push image run: | docker push ghcr.io/${{ github.repository }}/product-service:${{ github.sha }} |
ベストプラクティスまとめ
| 項目 | 推奨設定 |
|---|---|
| ブランチ戦略 | main(リリース) / feature/*(開発) / Pull Request によるコードレビュー必須 |
| テスト方針 | JUnit 5 + Testcontainers で統合テストを必ず走らせ、ローカル DB と同一イメージを使用 |
| イメージ管理 | GitHub Container Registry(GHCR)か Docker Hub に commit‑sha タグでプッシュし、Immutable なイメージとして扱う |
| デプロイ | 開発環境は docker compose up; 本番は Kubernetes + Argo CD へ移行する構成を想定 |
根拠:GitHub Actions の公式ガイド(https://docs.github.com/en/actions)と Spring Boot の Docker ビルド推奨パターン。
8. 全体まとめ & 次のステップ
- 開発基盤
-
JDK 21、Spring Boot 3.2、Spring Cloud 2023.0.1 を組み合わせた環境は、Java の最新機能と Spring エコシステムの成熟度を同時に享受できる。
-
マイクロサービス基盤
- Eureka(サービスディスカバリ)+ Config Server(外部設定)で「自律的かつ集中管理」な構成を実現。
-
Actuator + Micrometer + Prometheus/Grafana で運用時の可観測性を確保。
-
通信パターン
- OpenFeign → 同期呼び出し(軽量・Eureka 自動解決)
-
Spring Cloud Stream Function Model → 非同期イベント駆動(
@EnableBindingから脱却) -
コンテナ化 & デプロイ
- マルチステージ Dockerfile と
docker‑compose.ymlにより、ローカルで本番に近いマルチサービスクラスターを数分で起動。 -
CI(GitHub Actions)+ CD(GHCR → Kubernetes/Argo CD)でコード→デプロイまで自動化可能。
-
次の学習ステップ
- Kubernetes への移行:Spring Cloud Kubernetes の ConfigMap / Secret 統合を調べる。
- 分散トレーシング:Spring Cloud Sleuth → OpenTelemetry に置き換える実装例を試す。
- セキュリティ:Spring Security OAuth2 Resource Server と JWT を組み合わせた API 認可設計。
結論:本稿で示した手順とコードは、2025 年時点の公式最新スタックに完全対応しています(非推奨 API は除外し、Function‑style Stream へ置換)。これらをそのままプロジェクトに貼り付ければ、Spring Boot 3.2 + JDK 21 のモダンマイクロサービス基盤が即座に構築できます。
参考リンク集
| 内容 | URL |
|---|---|
| Spring Boot 3.2 Release Notes | https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.2-Release-Notes |
| Spring Cloud 2023.0 (BOM) | https://spring.io/projects/spring-cloud#overview |
| OpenFeign Reference | https://docs.spring.io/spring-cloud-openfeign/reference/html/ |
| Spring Cloud Stream Function Model | https://docs.spring.io/spring-cloud-stream/reference/html/function.html |
| Testcontainers Documentation | https://www.testcontainers.org/ |
| Micrometer Prometheus Registry | https://micrometer.io/docs/registry/prometheus |
| Docker Compose V2 Docs | https://docs.docker.com/compose/ |
| GitHub Actions Official Guide | https://docs.github.com/en/actions |
この記事は 2026 年 4 月 18 日に執筆され、最新の Spring エコシステム(Spring Boot 3.2、Spring Cloud 2023.0.1)を前提にしています。今後のマイナーバージョンアップ時には公式リリースノートをご確認ください。