Chuyển đến nội dung chính

第 21 課:Spring Boot 的 Docker 和容器化

Dockerfile 多階段建置。 Spring Boot 建置套件(雲端原生建置套件)。 Docker Compose 用於開發。 GraalVM 本機映像。容器最佳實務。

💻 程式設計 — 第 20 課 第 21 課:Docker 與容器化 春季啟動

Spring Boot 4:從基礎到高級

第 6 部分:微服務與生產

亞洲開發網

簡介

容器化是將 Spring Boot 應用程式投入生產的第一步。本文從基本的 Dockerfile 到多階段建置、Cloud Native Buildpacks、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 與 Native

指標JVM原生影像
啟動時間2-5秒50-200 毫秒
記憶體 (RSS)200-400MB50-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 Native Image:啟動 50-200ms,記憶體 50-100MB — 非常適合無伺服器
  • Docker Compose + Spring Boot Docker Compose 支援:開發時自動啟動依賴項

練習

1.為Spring Boot應用程式編寫多階段Dockerfile,分層提取。與單級比較影像大小 2. 建立完整的 docker-compose.yml:app + PostgreSQL + Redis。配置健康檢查和depends_on 3. 建構GraalVM Native Image,測量啟動時間和記憶體使用情況,與JVM模式進行比較