はじめに
コンテナー化は、Spring Boot アプリケーションを実稼働環境に導入するための最初のステップです。この記事では、基本的な Dockerfile からマルチステージ ビルド、Cloud Native Buildpack、GraalVM Native Image、ローカル開発用の Docker Compose までを説明します。
1. Dockerfile のマルチステージビルド
1.1 基本的な Dockerfile
# Stage 1: Build
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY gradle/ gradle/
COPY gradlew build.gradle.kts settings.gradle.kts ./
RUN ./gradlew dependencies --no-daemon
COPY src/ src/
RUN ./gradlew bootJar --no-daemon -x test
# Stage 2: Runtime
FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
USER appuser
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
1.2 最適化された階層化 Dockerfile
Spring Boot は階層化された JAR を作成し、Docker が効果的にキャッシュできるようにします。
FROM eclipse-temurin:21-jre-alpine AS builder
WORKDIR /app
COPY build/libs/*.jar app.jar
RUN java -Djarmode=tools -jar app.jar extract --layers --destination extracted
FROM eclipse-temurin:21-jre-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/extracted/dependencies/ ./
COPY --from=builder /app/extracted/spring-boot-loader/ ./
COPY --from=builder /app/extracted/snapshot-dependencies/ ./
COPY --from=builder /app/extracted/application/ ./
USER app
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
2. クラウドネイティブ ビルドパック
Spring Boot はビルドパックをサポートしています - Dockerfile を使用せずに Docker イメージを作成します。
# Gradle
./gradlew bootBuildImage --imageName=myapp:latest
# Maven
./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=myapp:latest
// build.gradle.kts — Customize
tasks.bootBuildImage {
imageName.set("registry.example.com/myapp:${version}")
environment.set(mapOf(
"BP_JVM_VERSION" to "21",
"BPE_JAVA_TOOL_OPTIONS" to "-XX:MaxRAMPercentage=75"
))
}
3. GraalVM ネイティブ イメージ
3.1 ネイティブ イメージのビルド
// build.gradle.kts
plugins {
id("org.graalvm.buildtools.native") version "0.10.6"
}
# Build native executable
./gradlew nativeCompile
# Build native Docker image
./gradlew bootBuildImage --imageName=myapp-native:latest
3.2 JVM とネイティブの比較
| メトリクス | JVM | ネイティブイメージ |
|---|---|---|
| 起動時間 | 2-5秒 | 50~200ミリ秒 |
| メモリ (RSS) | 200-400MB | 50~100MB |
| ビルド時間 | 10~30代 | 3~10分 |
| ピークスループット | 最高 | ~10 ~ 20% 低い |
| こんな方に最適 | 長期にわたるサービス | サーバーレス、CLI |
4. 開発用の Docker Compose
# docker-compose.yml
services:
app:
build: .
ports:
- "8080:8080"
environment:
SPRING_PROFILES_ACTIVE: docker
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/myapp
SPRING_DATASOURCE_USERNAME: postgres
SPRING_DATASOURCE_PASSWORD: postgres
SPRING_DATA_REDIS_HOST: redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:17-alpine
ports:
- "5432:5432"
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
4.1 Spring Boot Docker Compose のサポート
// build.gradle.kts
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
# application.yml
spring:
docker:
compose:
lifecycle-management: start-and-stop
file: docker-compose.yml
Spring Boot は、アプリの実行時に Docker Compose を自動的に起動し、接続プロパティを構成します。
5. コンテナのベストプラクティス
5.1 コンテナ用の JVM チューニング
ENTRYPOINT ["java", \
"-XX:MaxRAMPercentage=75", \
"-XX:+UseZGC", \
"-XX:+ZGenerational", \
"-Djava.security.egd=file:/dev/./urandom", \
"-jar", "app.jar"]
5.2 Docker でのヘルスチェック
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
5.3 .dockerignore
.git
.gradle
build/
!build/libs/*.jar
.idea
*.iml
node_modules
概要
- マルチステージ Dockerfile: ビルド ステージとランタイム ステージを分離し、イメージ サイズを大幅に削減します。
- クラウド ネイティブ ビルドパック: Dockerfile を使用せずに Docker イメージを作成します。
./gradlew bootBuildImage - GraalVM ネイティブ イメージ: 起動 50 ~ 200 ミリ秒、メモリ 50 ~ 100MB — サーバーレスに最適
- Docker Compose + Spring Boot Docker Compose サポート: 開発時に依存関係を自動的に開始します
演習
- 階層化抽出を使用して Spring Boot アプリ用のマルチステージ Dockerfile を作成します。シングルステージとの画像サイズの比較
- 完全な docker-compose.yml を作成します: app + PostgreSQL + Redis。 healthcheck と depend_on を構成する
- GraalVM Native Imageを構築し、起動時間とメモリ使用量を測定し、JVMモードと比較します。