Contents
前提条件と開発環境の準備
本セクションでは、マイクロサービスをローカルから本番環境まで一貫して動かすために最低限必要なツールと設定方法を解説します。各ツールは公式ドキュメント(2026‑05‑09 時点)に基づいているので、インストール手順でつまずくリスクが低減されます。また、環境変数の確認ポイントも合わせて示すため、作業後に「動作確認済み」かどうかをすぐに判断できます。
必要なツール一覧
以下のツールは いずれか の OS(Windows・macOS・Linux)で共通して利用できるものです。各項目の冒頭に簡単な説明文を入れ、続く箇条書きでインストール手順や確認コマンドを示します。
- JDK 21
- Oracle JDK または OpenJDK の公式サイトからダウンロードし、
JAVA_HOMEを設定してください。 -
java -versionが21.x.xと表示されればインストール完了です。 -
ビルドツール(Maven 3.9+ / Gradle 8.5+)
-
Maven は
mvn -v、Gradle はgradle -vでバージョンを確認できます。Spring Boot 3.2 が要求する最低バージョン以上がインストールされていることを必ずチェックしてください。 -
Docker & Docker Compose
-
Windows/macOS は Docker Desktop、Linux は Docker Engine を利用します。
docker versionとdocker compose versionがそれぞれ表示されれば準備完了です。 -
IDE(統合開発環境)
-
IntelliJ IDEA(Community または Ultimate)、Eclipse IDE for Enterprise Java Developers、VS Code + Java Extension Pack のいずれでも構築可能です。使用する IDE に合わせて「Spring Boot」「Lombok」「MapStruct」等のプラグインを追加してください。
-
Git
- Config Server が外部リポジトリと連携できるように、
git --versionが表示されることを確認します。認証が必要なプライベートリポジトリを利用する場合は SSH 鍵や Personal Access Token の設定も忘れずに行ってください。
ポイント
ツールのインストール後は必ずターミナルでecho $PATH、echo $JAVA_HOME(Windows はecho %JAVA_HOME%)を実行し、環境変数が正しく反映されているか確認しましょう。
プロジェクト雛形作成と依存関係設定
この章では Spring Initializr で生成したベースプロジェクトに対して、Spring Cloud 2023 系との互換性を保つための BOM 設定や、将来の非推奨化リスクへの対策方法を示します。正しい依存関係の管理はビルドエラー防止だけでなく、マイクロサービス全体のバージョン統一に直結する重要な作業です。
Spring Initializr の使い方
Spring Initializr は Web UI でも REST API でも利用できますが、ここでは最も一般的な GUI 手順を紹介します。
1. https://start.spring.io にアクセスし、以下の項目を設定して ZIP をダウンロードしてください。
| 項目 | 推奨値 |
|---|---|
| Project | Maven Project(Gradle でも可) |
| Language | Java |
| Spring Boot | 3.2.x (最新リリース) |
| Packaging | Jar |
| Java | 21 |
- Dependencies に次のモジュールを選択します。
Spring Web– REST API の土台Spring Data JPA– 永続化層Spring Cloud Discovery Client (Netflix Eureka)– サービスレジストリ(※後述)Config Server– 外部設定管理Gateway– API ゲートウェイLombok– ボイラープレート削減-
MapStruct– DTO ↔ Entity マッピング -
ダウンロードした ZIP を解凍し、IDE で Import すればプロジェクト雛形が完成します。
Spring Cloud 2023.x との互換性と Eureka のサポート状況
Spring Cloud 2023 系は spring-cloud-dependencies BOM によってバージョン管理されます。BOM を導入すると、個別のスターティングパッケージが自動的に適切なバージョンへ固定されるため、依存関係衝突を防げます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- pom.xml 例 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2023.0.2</version><!-- 2026‑05 時点の最新 --> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> |
|
1 2 3 4 5 6 7 |
// build.gradle.kts 例 dependencyManagement { imports { mavenBom("org.springframework.cloud:spring-cloud-dependencies:2023.0.2") } } |
Eureka の非推奨化リスク
- 公式情報(2026‑04‑30) によれば、
spring-cloud-starter-netflix-eureka-clientは 2024 年以降も機能的にサポートされていますが、将来的なメンテナンスコスト削減の観点から 「非推奨になる可能性」 が示唆されています。 - 現時点(2026‑05)では まだ利用可能 であり、既存プロジェクトへの影響はありませんが、長期的なロードマップを考慮すると Consul や Zookeeper などの代替ディスカバリサービスへの移行計画を立てることが推奨されます。
- 詳細は公式リリースノート(Spring Cloud 2023.0.x Release Notes)をご確認ください。
実務的な対策
-pom.xmlにeureka-clientを明示的に記述しつつ、同時にspring-cloud-starter-consul-discoveryも依存追加しておくと、コードベースの差分が最小限で済みます。
- アプリケーションプロパティでspring.cloud.discovery.client.simple.instances.*を利用できるようにしておくと、テスト時にローカルモックへ切り替えやすくなります。
コアコンポーネント実装
この章ではマイクロサービス基盤の中核である Eureka Server、Config Server、API Gateway の最小構成コードと必須設定ファイルを示します。各コンポーネントは単体テストが可能なように設計し、後続サービスがシームレスに統合できることを前提にしています。
Eureka サービスレジストリ
Eureka Server は @EnableEurekaServer アノテーションだけで起動できます。以下のコードは 最小構成 ですので、まずはローカルで動作確認してください。
|
1 2 3 4 5 6 7 8 |
@SpringBootApplication @EnableEurekaServer // Eureka を有効化 public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } |
- 設定ファイル(
src/main/resources/application.yml)
yaml
server:
port: 8761
eureka:
client:
register-with-eureka: false # サーバー自身は登録しない
fetch-registry: false # 他のレジストリも取得しない
instance:
hostname: localhost
注意点
Spring Cloud 2023.x ではeureka.client.service-url.defaultZoneが必須です。クライアント側で正しい URL を設定していないと、起動時に「Eureka server not reachable」の警告が出ます。
クライアント側の基本設定
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# src/main/resources/bootstrap.yml(Spring Cloud 2023.x 推奨) spring: application: name: product-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ register-with-eureka: true fetch-registry: true |
@EnableDiscoveryClient を付与したサービスは自動的に Eureka に登録されます。
Config Server 設定
Config Server は外部 Git リポジトリと連携させるだけで、プロファイル別設定を即座に配信できます。以下のコードは シンプルな構成 です。
|
1 2 3 4 5 6 7 8 |
@SpringBootApplication @EnableConfigServer // Config Server を有効化 public class ConfigServerApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerApplication.class, args); } } |
- 設定例(
application.yml)
yaml
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/your-org/microservice-config.git
clone-on-start: true # 起動時にリポジトリをクローン
timeout: 5 # タイムアウト秒数(任意)
ベストプラクティス
- プライベートリポジトリの場合はusernameとpassword(または PAT)を環境変数で渡す。
- 設定ファイル名は{application}-{profile}.yml形式に統一し、CI パイプラインで自動生成すると管理が楽になります。
API Gateway 構成
Spring Cloud Gateway は RouteLocatorBuilder による DSL でルーティングとフィルタを定義します。以下は 基本的なルート と カスタムロギングフィルタ のサンプルです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Configuration public class GatewayConfig { @Bean public RouteLocator customRoutes(RouteLocatorBuilder builder) { return builder.routes() // product-service への API パスを定義 .route("product_service_route", r -> r.path("/api/products/**") .uri("lb://PRODUCT-SERVICE")) // Eureka のロードバランサー利用 .build(); } @Bean public GlobalFilter loggingFilter() { return (exchange, chain) -> { ServerHttpRequest request = exchange.getRequest(); System.out.println("Incoming request: " + request.getMethod() + " " + request.getURI()); return chain.filter(exchange); }; } } |
- gateway の
application.yml(CORS とヘルスチェックの例)
yaml
spring:
cloud:
gateway:
globalcors:
corsConfigurations:
'[/*]':
allowedOrigins: ""
allowedMethods:
- GET
- POST
- PUT
- DELETE
management:
endpoints:
web:
exposure:
include: health,info,gateway
補足
複数サービスが増える場合はapplication.ymlのroutes:配列で一元管理すると可読性が向上します。
コンテナ化・ローカルスタック起動と Kubernetes デプロイ
マイクロサービスを Docker 化し、Docker Compose でローカル環境を再現する手順と、Kind または Minikube を用いた軽量 K8s クラスタへのデプロイ方法を示します。コンテナ化により「動作する環境がどこでも同じ」という保証が得られ、本番リリース前の検証が格段に楽になります。
Dockerfile と Docker Compose(修正版)
Dockerfile は マルチステージビルド を採用し、最終イメージは JDK 21 の JRE だけを残すことでサイズを 150 MB 以下に抑えられます。以下のポイントで以前の誤植を修正しています。
WORKDI R→ 正しくはWORKDIR- ビルドステージとランタイムステージの分離を明示
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# ---------- Build stage ---------- FROM eclipse-temurin:21-jdk as builder WORKDIR /app # Maven wrapper と pom.xml を先にコピーして依存解決だけをキャッシュ COPY mvnw pom.xml ./ COPY .mvn .mvn RUN ./mvnw dependency:go-offline -B # ソースコード全体をコピーし、テストはスキップしてパッケージング COPY src src RUN ./mvnw clean package -DskipTests # ---------- Runtime stage ---------- FROM eclipse-temurin:21-jre WORKDIR /app # ← 修正済み COPY --from=builder /app/target/*.jar app.jar ENTRYPOINT ["java","-jar","/app/app.jar"] |
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 |
version: "3.9" services: eureka-server: build: ./eureka-server ports: - "8761:8761" environment: TZ: Asia/Tokyo config-server: build: ./config-server ports: - "8888:8888" gateway: build: ./gateway ports: - "8080:8080" depends_on: - eureka-server - config-server product-service: build: ./product-service environment: SPRING_PROFILES_ACTIVE: dev depends_on: - eureka-server - config-server |
docker compose up --build を実行すると、4 つのコンテナが同時に起動し、http://localhost:8080/api/products へアクセスできることを確認してください。
Kind / Minikube へのデプロイ手順
ローカル K8s クラスタは Kind(Docker 上で動く軽量クラスター)か Minikube のどちらでも構いません。ここでは Kind を例に、マニフェスト作成からデプロイまでの流れを示します。
-
クラスタ作成
bash
kind create cluster --name ms-demo
# Minikube なら: minikube start -
ローカルイメージのレジストリ登録
Docker イメージを Kind の内部レジストリにプッシュします。
bash
docker tag eureka-server:latest kind.local/eureka-server:latest
kind load docker-image kind.local/eureka-server:latest --name ms-demo
# 他のサービスも同様にロード
- Kubernetes マニフェスト(例)
k8s/ディレクトリ配下にdeployment.yamlとservice.yamlを配置します。
yaml
# k8s/gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway
spec:
replicas: 2
selector:
matchLabels:
app: gateway
template:
metadata:
labels:
app: gateway
spec:
containers:
- name: gateway
image: kind.local/gateway:latest
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: gateway-svc
spec:
type: NodePort
selector:
app: gateway
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 任意のポート
-
マニフェスト適用
bash
kubectl apply -f k8s/ -
動作確認
bash
kubectl get pods -o wide
curl http://localhost:30080/api/products # NodePort 経由でアクセス
Tip:Ingress を利用すれば、外部からの HTTPS アクセスやドメイン名ベースのルーティングが可能です。
ingress-nginxコントローラを追加すると、本番に近い構成でテストできます。
テスト戦略・CI/CD・運用のベストプラクティス
マイクロサービスは 単体テスト、統合テスト、パフォーマンステスト を段階的に実施し、さらに自動化された CI/CD パイプラインでデリバリーを高速化します。ここでは Testcontainers を用いた本物コンテナ環境でのテスト例と、GitHub Actions によるフルパイプライン、そして運用段階で重要になる Observability と Security のポイントをまとめます。
統合テスト(Testcontainers)
Testcontainers は Docker コンテナを起動したまま JUnit テストを実行できるため、Eureka や Config Server など外部依存サービスの挙動を 実環境に近い形で検証 できます。以下は product-service の統合テスト例です。
|
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 |
@Testcontainers @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class ProductServiceIntegrationTest { @Container static GenericContainer<?> eureka = new GenericContainer<>("springcloud/eureka:2023.0.2") .withExposedPorts(8761); @DynamicPropertySource static void registerEureka(DynamicPropertyRegistry registry) { String uri = "http://%s:%d/eureka/".formatted(eureka.getHost(), eureka.getFirstMappedPort()); registry.add("eureka.client.service-url.defaultZone", () -> uri); } @Autowired private TestRestTemplate restTemplate; @Test void shouldCreateProduct() { ProductCreateDto dto = new ProductCreateDto("Sample", BigDecimal.valueOf(99.9)); ResponseEntity<ProductDto> resp = restTemplate.postForEntity("/api/products", dto, ProductDto.class); assertEquals(HttpStatus.CREATED, resp.getStatusCode()); assertNotNull(resp.getBody().getId()); } } |
- ポイント
@DynamicPropertySourceによりテスト実行時に Eureka の URL が自動で注入されます。- テストは
mvn verify(または./gradlew check)だけで完結し、CI 上でも同様に動作します。
GitHub Actions パイプライン
以下は ビルド → テスト → Docker イメージ作成 → Kind デプロイ を自動化したサンプルです。GitHub の main ブランチへの push がトリガーになります。
|
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 54 55 56 57 58 59 60 |
name: CI/CD on: push: branches: [ main ] jobs: build-test-deploy: runs-on: ubuntu-latest steps: # ソースコード取得 - uses: actions/checkout@v4 # JDK21 セットアップ - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: temurin java-version: '21' # Maven ビルド & テスト(Testcontainers が利用できるように Docker デーモンを有効化) - name: Set up Docker for Testcontainers uses: docker/setup-buildx-action@v2 - name: Build and verify with Maven run: ./mvnw -B clean verify # Docker イメージ作成(マルチステージ Dockerfile を利用) - name: Build Docker images run: | docker compose build # GitHub Container Registry にプッシュ - name: Log in to GHCR env: CR_PAT: ${{ secrets.GITHUB_TOKEN }} run: echo "$CR_PAT" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - name: Push images run: | IMAGE=ghcr.io/${{ github.repository }}/eureka-server:latest docker tag eureka-server $IMAGE docker push $IMAGE # 他サービスも同様にプッシュ # Kind クラスタ作成 & デプロイ - name: Set up Kind uses: engineerd/setup-kind@v0.5.0 with: version: v0.20.0 - name: Load images into Kind run: | kind load docker-image ghcr.io/${{ github.repository }}/eureka-server:latest # 他サービスも同様にロード - name: Deploy to Kind run: kubectl apply -f k8s/ |
- ベストプラクティス
testcontainers用に Docker デーモンを有効化し、CI 環境でもローカルと同等のテストが走るようにする。- イメージは GitHub Container Registry(GHCR)へプッシュし、K8s クラスタで直接参照できるように
kind loadを実行する。
Observability とパフォーマンスチューニング
| 項目 | 推奨設定・ツール |
|---|---|
| JVM オプション | -XX:MaxRAMPercentage=75 -XX:+UseZGC -Djava.security.egd=file:/dev/./urandom(JDK 21 の ZGC は低レイテンシに有効) |
| メトリクス収集 | spring-boot-starter-actuator + micrometer-registry-prometheus を依存追加し、/actuator/prometheus エンドポイントを公開。Grafana で可視化するとボトルネックが把握しやすい。 |
| ログ集約 | Logback の JSON レイアウト+EFK(Elasticsearch‑Fluentd‑Kibana)または Loki‑Promtail‑Grafana スタックを採用。サービス間の相関検索に役立つ。 |
| リソース制限 | Docker Compose では deploy.resources.limits、K8s では resources.requests/limits を明示的に設定し、CPU・メモリ不足による OOM キラーを防止。 |
| ヘルスチェック | Spring Boot Actuator の health エンドポイントを K8s の Liveness/Readiness Probe にマッピング。障害時の自動再起動が可能になる。 |
セキュリティ考慮事項
- 通信暗号化
- Service‑to‑Service 間は Spring Cloud LoadBalancer が内部で HTTP を使用するため、必ず
gatewayの外部エンドポイントだけ HTTPS にし、Ingress で TLS 終端を行う。 - 認可・認証
- Spring Security と OAuth2 Resource Server(Keycloak 等)を組み合わせ、Gateway でトークン検証を集中させると各サービスの実装がシンプルになる。
- コンテナイメージの脆弱性スキャン
- GitHub Actions の
trivyアクションや Dependabot を利用し、ビルド時に CVE を自動検出・通知するパイプラインを構築する。
まとめ:上記の Observability と Security の設定は「開発完了」だけでなく「運用開始」直後にも必ず実装すべき項目です。早期に組み込むほど、障害対応コストが大幅に削減できます。
まとめ
本稿では Spring Boot 3.2 と JDK 21 を基盤としたマイクロサービスアーキテクチャの全体像を、環境構築 → プロジェクト雛形作成 → コアコンポーネント実装 → コンテナ化・K8s デプロイ → テスト・CI/CD・運用 というフローで体系的に解説しました。特に以下の点が重要です。
| 項目 | キーポイント |
|---|---|
| 環境準備 | JDK 21、Docker、IDE の正しいインストールと環境変数設定 |
| 依存管理 | Spring Cloud 2023.x BOM によるバージョン統一、Eureka の非推奨リスクを認識 |
| コンテナ化 | WORKDIR 修正済みのマルチステージ Dockerfile、docker‑compose でローカルスタック再現 |
| K8s デプロイ | Kind/Minikube へのイメージロードとマニフェスト管理 |
| CI/CD | Testcontainers + GitHub Actions によるフルパイプライン自動化 |
| Observability & Security | Actuator+Prometheus、TLS/OAuth2、脆弱性スキャンの導入 |
次のステップ
1. 本記事の手順でローカルスタックを構築し、すべてのサービスが期待通りに起動することを確認。
2. GitHub リポジトリへコードをプッシュし、CI が自動でビルド・テスト・デプロイできるか検証。
3. 本番環境用に Helm Chart を作成し、実際のクラウド(EKS/GKE 等)へ展開してみる。
この一連の流れを習得すれば、Spring Boot と JDK 21 の最新スタックで スケーラブルかつ保守性の高いマイクロサービス を自信を持って提供できるようになります。ぜひサンプルリポジトリをクローンし、ハンズオン形式で体験してみてください。