Contents
- 1 1️⃣ 前提条件と開発ツールのインストール
- 2 2️⃣ Spring Initializr で雛形プロジェクトを作成
- 3 3️⃣ サービスディスカバリ & 設定管理(Eureka / Consul + Config Server)
- 4 4️⃣ REST API と自動ドキュメント、Docker イメージの作成
- 5 5️⃣ Kubernetes デプロイ、CI/CD パイプライン、Observability & Security
- 6 6️⃣ 参考リンク(公式ドキュメント)
- 7 まとめ
1️⃣ 前提条件と開発ツールのインストール
1.1 必要なコンポーネント
| コンポーネント | 推奨バージョン (執筆時点) | 備考 |
|---|---|---|
| JDK | 21(LTS) | Spring Boot 3 系は Java 17+ が必須。最新の LTS を使用すると長期サポートが受けられる |
| IDE | IntelliJ IDEA (Community/Ultimate) または Visual Studio Code | どちらも Java 用プラグインが充実 |
| ビルドツール | Maven 3.9.x、Gradle 8.5+ | プロジェクトの好みで選択可 |
| コンテナランタイム | Docker Engine 27.x 以上 | Windows/macOS/Linux 共通 |
1.2 OS 別インストール手順
macOS
| ツール | インストールコマンド |
|---|---|
| SDKMAN!(JDK 管理) | curl -s "https://get.sdkman.io" \| bash && source "$HOME/.sdkman/bin/sdkman-init.sh" |
| JDK 21 | sdk install java 21-open |
| IntelliJ IDEA Community | brew install --cask intellij-idea-ce |
| VS Code + Java 拡張 | brew install --cask visual-studio-code && code --install-extension vscjava.vscode-java-pack |
| Maven / Gradle | brew install maven gradle |
Ubuntu/Debian 系 Linux
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 1. SDKMAN! のインストール(macOS と同様) curl -s "https://get.sdkman.io" | bash source "$HOME/.sdkmanager/bin/sdkman-init.sh" # 2. JDK21 の導入 sdk install java 21-open # 3. IDE のインストール例 sudo snap install intellij-idea-community --classic # IntelliJ IDEA Community sudo snap install code --classic # VS Code # 4. ビルドツール sudo apt update && sudo apt install -y maven gradle |
Windows(PowerShell)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# 1. Chocolatey のインストール(管理者権限で実行) Set-ExecutionPolicy Bypass -Scope Process -Force; ` [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12; ` iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) # 2. SDKMAN! の代替として `jabba` を使用 choco install jabba -y jabba install adoptopenjdk@21.0.2-9 # JDK 21 # 3. IDE のインストール choco install intellijidea-community -y # IntelliJ IDEA Community choco install vscode -y # VS Code # 4. Maven / Gradle choco install maven gradle -y |
ポイント
macOS は Homebrew がデファクトスタンダード、Linux はapt/yum系に加えて Snap や SDKMAN! を併用、Windows は Chocolatey (または Scoop) が便利です。
いずれの環境でもjava -version/mvn -v/gradle -vが期待通りに表示されればインストール完了です。
2️⃣ Spring Initializr で雛形プロジェクトを作成
2.1 Spring Initializr の利用方法
| 項目 | 設定例 |
|---|---|
| URL | https://start.spring.io |
| Project | Maven (または Gradle) |
| Language | Java |
| Spring Boot | 3.2.x(最新マイナーバージョン) |
| Group / Artifact | com.example / order-service |
| Java Version | 21 |
| Dependencies | Web, Eureka Client, Config Client, Actuator, OpenFeign, SpringDoc OpenAPI UI |
備考:Spring Boot のバージョンは「最新安定版」を選択してください。公式ページの Release Notes を随時確認すると、マイナーバグ修正や新機能が把握できます。
2.2 生成された 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 49 50 51 52 53 54 55 56 57 |
<properties> <java.version>21</java.version> <!-- Spring Cloud のバージョンは BOM に委譲 --> <spring-cloud.version>2024.0.x</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- Spring Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Eureka Client --> <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> <!-- Actuator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- OpenFeign --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!-- SpringDoc OpenAPI UI --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.5.0</version> </dependency> </dependencies> |
2.3 プロジェクトのインポート
| IDE | 手順 |
|---|---|
| IntelliJ IDEA | File → New → Project from Existing Sources → pom.xml を選択し、Maven が自動的に依存を解決します |
| VS Code | 拡張機能 Java Extension Pack が有効なら、プロジェクトルートで Ctrl+Shift+P → Java: Import Maven Projects |
3️⃣ サービスディスカバリ & 設定管理(Eureka / Consul + Config Server)
3.1 Eureka Server の作成
|
1 2 3 4 5 6 |
curl https://start.spring.io/starter.zip \ -d dependencies=web,eureka-server,actuator \ -d name=eureka-server \ -d packageName=com.example.eureka \ -o eureka-server.zip && unzip eureka-server.zip -d eureka-server |
src/main/resources/application.yml
|
1 2 3 4 5 6 7 8 9 10 |
server: port: 8761 eureka: client: register-with-eureka: false # 自身はレジストリに登録しない fetch-registry: false server: enable-self-preservation: false |
起動クラス
|
1 2 3 4 5 6 7 8 |
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } } |
起動後は http://localhost:8761/ に管理画面が表示されます。
3.2 Config Server の作成
|
1 2 3 4 5 6 |
curl https://start.spring.io/starter.zip \ -d dependencies=web,config-server,git,actuator \ -d name=config-server \ -d packageName=com.example.config \ -o config-server.zip && unzip config-server.zip -d config-server |
src/main/resources/application.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 |
server: port: 8888 spring: cloud: config: server: git: uri: https://github.com/your-org/microservice-config.git default-label: main clone-on-start: true |
ポイント
*git.uriはプライベートリポジトリでも構いません。その場合は認証情報(SSH キーや Personal Access Token)を環境変数で渡すのが安全です。
3.3 クライアント側設定例(order‑service)
bootstrap.yml(Spring Boot 2.x 系から推奨されていたファイルですが、Spring Boot 3 でも有効です)
|
1 2 3 4 5 6 7 8 9 |
spring: application: name: order-service eureka: client: service-url: defaultZone: http://localhost:8761/eureka/ |
application.yml(ローカルプロパティの上書き例)
|
1 2 3 4 5 6 |
management: endpoints: web: exposure: include: health,info,prometheus |
この構成で、サービスは起動時に Eureka に登録し、外部化された設定は Config Server から取得します。
4️⃣ REST API と自動ドキュメント、Docker イメージの作成
4.1 コントローラ・サービス実装(簡易サンプル)
|
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 |
package com.example.orderservice.controller; import lombok.RequiredArgsConstructor; import org.springframework.http.*; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/orders") @RequiredArgsConstructor @Validated public class OrderController { private final OrderService orderService; @GetMapping("/{id}") public ResponseEntity<OrderDto> get(@PathVariable Long id) { return ResponseEntity.ok(orderService.findById(id)); } @PostMapping public ResponseEntity<OrderDto> create(@RequestBody @Valid OrderCreateRequest req) { var created = orderService.create(req); return new ResponseEntity<>(created, HttpStatus.CREATED); } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.example.orderservice.service; import org.springframework.stereotype.Service; import java.util.*; @Service public class OrderService { private final Map<Long, OrderDto> store = new HashMap<>(); public OrderDto findById(Long id) { return Optional.ofNullable(store.get(id)) .orElseThrow(() -> new NoSuchElementException("Order not found")); } public OrderDto create(OrderCreateRequest req) { var id = (long) (store.size() + 1); var dto = new OrderDto(id, req.productCode(), req.quantity()); store.put(id, dto); return dto; } } |
ベストプラクティス
ビジネスロジックは必ず@Serviceに分離し、コントローラはリクエスト/レスポンスの変換に専念させます。
DTO と Request オブジェクトは record(Java 21)で定義するとコード量が大幅に削減できます。
4.2 OpenAPI (Springdoc) の自動生成
pom.xml に以下依存を追加しただけで、起動時に Swagger UI が有効になります。
|
1 2 3 4 5 6 |
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.5.0</version> </dependency> |
アクセス URL: http://localhost:8080/swagger-ui.html
※ application.yml でベースパスを変更した場合はそのプレフィックスに合わせてください。
4.3 Dockerfile(マルチステージビルド)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# ---------- Build Stage ---------- FROM maven:3.9-eclipse-temurin-21 AS builder WORKDIR /src COPY pom.xml . COPY src ./src RUN mvn -B package -DskipTests # ---------- Runtime Stage ---------- FROM eclipse-temurin:21-jre-alpine ARG JAR_FILE=/src/target/*.jar COPY --from=builder ${JAR_FILE} app.jar ENTRYPOINT ["java","-XX:+UseContainerSupport","-jar","/app.jar"] |
ビルド・実行例
|
1 2 3 4 5 6 |
# Docker イメージ作成 docker build -t order-service:3.2.x . # ローカルで起動(ポート 8080 を公開) docker run --rm -p 8080:8080 order-service:3.2.x |
ポイント
-XX:+UseContainerSupportは JDK 21 以降のデフォルトですが、明示的に書くとコンテナリソース制限が正しく反映されます。
Alpine ベースはサイズが小さく、脆弱性スキャンの対象面も減ります。
5️⃣ Kubernetes デプロイ、CI/CD パイプライン、Observability & Security
5️⃣1 Helm Chart(order‑service 用)
|
1 2 3 4 5 6 7 8 |
order-service/ ├── Chart.yaml ├── values.yaml └── templates/ ├── deployment.yaml ├── service.yaml └── ingress.yaml |
Chart.yaml
|
1 2 3 4 5 6 7 |
apiVersion: v2 name: order-service description: Order Service Helm chart type: application version: 0.1.0 appVersion: "3.2.x" |
values.yaml(主要パラメータ)
|
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 |
replicaCount: 2 image: repository: your-dockerhub/order-service pullPolicy: IfNotPresent tag: latest # CI が SHA を上書きします service: type: ClusterIP port: 8080 resources: limits: cpu: "500m" memory: "512Mi" requests: cpu: "250m" memory: "256Mi" ingress: enabled: true className: nginx hosts: - host: order.example.com paths: - path: / pathType: Prefix |
templates/deployment.yaml(重要ポイントにコメント)
|
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 |
apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "order-service.fullname" . }} labels: {{- include "order-service.labels" . | nindent 4 }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app.kubernetes.io/name: {{ include "order-service.name" . }} template: metadata: annotations: prometheus.io/scrape: "true" prometheus.io/port: "{{ .Values.service.port }}" labels: app.kubernetes.io/name: {{ include "order-service.name" . }} spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" ports: - containerPort: {{ .Values.service.port }} envFrom: - configMapRef: name: order-service-config readinessProbe: httpGet: path: /actuator/health port: {{ .Values.service.port }} initialDelaySeconds: 10 periodSeconds: 5 |
5️⃣2 GitHub Actions による CI/CD(ci-cd.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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
name: CI / CD on: push: branches: [ main ] jobs: build-test: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: temurin java-version: '21' cache: maven - name: Build & run unit tests run: | mvn -B verify --file pom.xml - name: Publish test results uses: actions/upload-artifact@v4 with: name: surefire-reports path: target/surefire-reports/ docker-push-deploy: needs: build-test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASS }} - name: Build & push image (SHA tag) run: | IMAGE=${{ secrets.DOCKER_USER }}/order-service:${{ github.sha }} docker build -t $IMAGE . docker push $IMAGE - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'v1.30.0' - name: Deploy to Kubernetes (Helm) env: KUBECONFIG: ${{ secrets.KUBE_CONFIG }} run: | helm upgrade --install order-service ./helm/order-service \ --set image.tag=${{ github.sha }} \ --namespace microservice-demo --create-namespace |
補足
KUBE_CONFIGは GitHub のシークレットに Base64 エンコードした kubeconfig を保存し、env:でデコードして使用します。
Windows ランナーが必要な場合はruns-on: windows-latestに変更し、Docker Desktop がインストールされた環境を用意してください。
5️⃣3 Observability(メトリクス・トレーシング・ログ)
5.3.1 Micrometer + Prometheus
|
1 2 3 4 5 6 7 8 9 10 11 |
# src/main/resources/application.yml management: endpoints: web: exposure: include: health,info,prometheus metrics: export: prometheus: enabled: true |
Prometheus の scrape_configs に以下を追加:
|
1 2 3 4 5 |
- job_name: 'order-service' static_configs: - targets: ['order-service.default.svc.cluster.local:8080'] metrics_path: '/actuator/prometheus' |
5.3.2 Zipkin(分散トレーシング)
pom.xml に依存を追加:
|
1 2 3 4 5 |
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zipkin</artifactId> </dependency> |
application.yml 設定例:
|
1 2 3 4 5 6 7 |
spring: zipkin: base-url: http://zipkin:9411/ sleuth: sampler: probability: 0.5 # 本番では 0.1 程度に抑える |
5.3.3 ログ集約(ELK)
|
1 2 3 4 5 6 |
<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>7.4</version> </dependency> |
src/main/resources/logback-spring.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 |
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>${LOGSTASH_HOST:logstash}:5000</destination> <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder"> <providers> <timestamp/> <pattern> <pattern> { "level": "%level", "logger": "%logger", "thread": "%thread", "message": "%msg" } </pattern> </pattern> </providers> </encoder> </appender> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="LOGSTASH"/> </root> |
ポイント
* コンテナ環境ではLOGSTASH_HOSTを環境変数で注入し、Fluent Bit → Elasticsearch へ転送する構成が一般的です。
5️⃣4 Security – JWT 認証
依存関係(pom.xml)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.12.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.12.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.12.5</version> <scope>runtime</scope> </dependency> |
セキュリティ設定(SecurityConfig.java)
|
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 |
@EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { private final JwtProvider jwtProvider; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers( "/swagger-ui.html/**", "/v3/api-docs/**", "/actuator/health" ).permitAll() .anyRequest().authenticated() .and() .addFilterBefore(new JwtAuthenticationFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class); } } |
JWT プロバイダーの概略実装
|
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 |
@Component @RequiredArgsConstructor public class JwtProvider { private final SecretKey secretKey = Keys.hmacShaKeyFor( Base64.getDecoder().decode(System.getenv("JWT_SECRET")) ); public String createToken(String username, List<String> roles) { return Jwts.builder() .setSubject(username) .claim("roles", roles) .setIssuedAt(new Date()) .setExpiration(Date.from(Instant.now().plus(2, ChronoUnit.HOURS))) .signWith(secretKey, SignatureAlgorithm.HS256) .compact(); } public boolean validate(String token) { try { Jwts.parserBuilder() .setSigningKey(secretKey) .build() .parseClaimsJws(token); return true; } catch (JwtException e) { return false; } } public String getUsername(String token) { return Jwts.parserBuilder() .setSigningKey(secretKey) .build() .parseClaimsJws(token) .getBody() .getSubject(); } } |
ベストプラクティス
JWT_SECRETは必ず 環境変数 か Kubernetes Secret に保存し、コードにハードコーディングしないこと。
トークンの有効期限は用途に合わせて短め(15‑30 分)に設定し、リフレッシュトークンで延長する構成が推奨されます。
6️⃣ 参考リンク(公式ドキュメント)
| 項目 | URL |
|---|---|
| Spring Boot 3.2.x リファレンス | https://docs.spring.io/spring-boot/docs/current/reference/html/ |
| Spring Cloud 2024.0.x (Hoxton) | https://spring.io/projects/spring-cloud |
| Spring Initializr | https://start.spring.io |
| Spring Cloud Eureka | https://cloud.spring.io/spring-cloud-netflix/reference/html/#spring-cloud-eureka-server |
| Spring Cloud Config Server | https://docs.spring.io/spring-cloud-config/reference/ |
| Springdoc OpenAPI 3 | https://springdoc.org/ |
| Micrometer & Prometheus Integration | https://micrometer.io/docs/registry/prometheus |
| Zipkin with Spring Cloud Sleuth | https://spring.io/guides/gs/distributed-tracing/ |
| Helm Charts のベストプラクティス | https://helm.sh/docs/topics/charts/ |
| GitHub Actions for Java | https://docs.github.com/en/actions/language-and-framework-guides/building-and-testing-java-with-maven |
上記リンクはすべて公式または広く信頼されたリソースです。外部の未確認サイトへの依存は排除しました。
まとめ
- OS に合わせた JDK/IDE のインストール を最初に完了させる(macOS・Linux・Windows 各対応)。
- Spring Initializr で必要なスターターを選択し、
pom.xml/build.gradleに BOM を導入すれば依存管理がシンプルになる。 - Eureka + Config Server の組み合わせでサービスディスカバリと外部化設定を実装。
- Springdoc OpenAPI が自動生成する Swagger UI と、マルチステージ Dockerfile により開発から本番デプロイまで一貫したフローが確立できる。
- Helm + GitHub Actions で Kubernetes への継続的デリバリーを実現し、Micrometer/Prometheus, Zipkin, ELK による可観測性、そして JWT + Spring Security による API 保護を組み込む。
この手順書は「最新安定版」前提で作成していますが、バージョンは随時公式リリースノートで確認し、<properties> や helm values の値を書き換えて運用してください。
本稿の内容は 2026‑04‑15 時点の情報に基づいています。技術スタックは急速に進化するため、公式ドキュメントやリリースノートで定期的な見直しを行うことを推奨します。