Docker 化与优雅停机、健康检查配合
Java 应用最终要跑在服务器上。Docker 镜像把运行环境固化,编排平台按健康状态调度流量。优雅停机保证发版时存量请求不中断,健康检查让平台知道何时能安全摘流/重启。三者配合是生产级部署的底线。示例基于 Boot 3.x。
打包与 Dockerfile
Boot 的可执行 jar 由 spring-boot-maven-plugin 的 repackage 生成。镜像用多阶段构建压缩体积:
# 阶段一:编译
FROM maven:3.9-eclipse-temurin-17 AS build
WORKDIR /app
COPY pom.xml .
RUN mvn -q dependency:go-offline # 预拉依赖
COPY src ./src
RUN mvn -q -DskipTests package
# 阶段二:只保留运行环境
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY --from=build /app/target/*.jar app.jar
EXPOSE 8080
# 健康检查:镜像需自带 curl(或用 wget),基础镜像不自带要自行安装
HEALTHCHECK --interval=10s --timeout=3s --start-period=40s --retries=3 \
CMD curl -fs http://localhost:8080/actuator/health || exit 1
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]
-XX:MaxRAMPercentage=75 让 JVM 按容器内存限额自动取堆大小,避免堆配死导致容器 OOM。
优雅停机配置
server:
shutdown: graceful # 收到 SIGTERM 后停止接收新请求
spring:
lifecycle:
timeout-per-shutdown-phase: 30s # 给在途请求最多 30 秒处理完
行为链:平台发 SIGTERM → 应用进入停机阶段,readiness 探针转 DOWN(流量先被摘掉)→ 等待在途请求/定时任务结束,超过 30 秒强制退出。未开启 graceful 时默认直接关闭,正在处理的请求会被打断。
与健康检查探针配合
Actuator 提供两组探针(第 26 章),容器编排平台应分别使用:
management:
endpoint:
health:
probes:
enabled: true # 暴露 /actuator/health/liveness 与 /actuator/health/readiness
- liveness(存活):进程僵死则平台重启容器;
- readiness(就绪):依赖(DB、Redis)不可用或正在停机时返回 DOWN,平台停止转发新流量。
docker-compose 里等依赖就绪再启动服务:
services:
app:
build: .
ports: ["8080:8080"]
depends_on:
db:
condition: service_healthy
db:
image: mysql:8
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
K8s 用同语义的 livenessProbe/readinessProbe 指向同一组探针路径,滚动发布时新 Pod readiness 通过才接流量、旧 Pod 优雅退出。
补充习惯
- 时区:
ENV TZ=Asia/Shanghai(配合第 43 章时区坑); - 配置外置:数据库地址、密钥用环境变量/配置中心注入,镜像不绑环境;
- 日志输出到 stdout 由采集器统一收集,别写容器内文件;
- 用非 root 用户运行(镜像内
USER指令)降低风险。
小结:多阶段 Dockerfile 产出精简镜像;server.shutdown=graceful + 超时做优雅停机;Actuator 的 liveness/readiness 探针告诉编排平台何时重启、何时接流量,三者配齐才算能上生产的部署。