Java容器化关键步骤:用openjdk:17-jre-slim镜像、可执行JAR、ENTRYPOINT["java","-jar","/app.jar"];启用UseContainerSupport自动适配内存限制;配置Actuator健康检查确保K8s就绪识别。

Java应用打包成Docker镜像的关键步骤
直接用 openjdk 基础镜像最稳妥,别自己装 JDK。官方 openjdk:17-jre-slim 已包含运行时、精简体积、更新及时,比 openjdk:17-jdk 更适合生产部署。
- 确保
JAR包是可执行的(含META-INF/MANIFEST.MF中的Main-Class或Start-Class) -
Dockerfile中用COPY复制 JAR 后,ENTRYPOINT ["java","-jar","/app.jar"]是最简启动方式 - 避免在镜像中写死
-Xmx:改用java -XX:+UseContainerSupport -jar /app.jar,让 JVM 自动识别容器内存限制(JDK 8u191+/10+ 默认启用) - 工作目录设为
/app,JAR 名统一用app.jar,减少 ENTRYPOINT 维护成本
常见启动失败原因与日志定位方法
容器秒退或报 Exit 1,大概率是 JVM 启动参数或类路径问题,不是代码 bug。
- 先用
docker run --rm -it your-image:tag sh进容器,手动执行java -jar /app.jar看原始错误输出 - 如果报
UnsupportedClassVersionError,说明编译 JDK 版本 > 容器内 JRE 版本,比如用 JDK 21 编译却用了openjdk:11-jre-slim - 如果报
NoClassDefFoundError且涉及 Spring Boot,检查是否误用了mvn compile而非mvn package—— 只有package生成的 fat jar 才能直接-jar - Spring Boot 应用默认不打印启动完成日志到 stdout,加
--logging.level.org.springframework.boot.StartupInfoLogger=DEBUG或确认spring.main.banner-mode=off不影响日志可见性
如何正确传递 JVM 内存参数给容器化 Java 进程
硬写 -Xmx512m 是反模式。容器有内存 limit,JVM 却看不见,会 OOM Kill。
- 必须启用容器感知:JDK 8u191+ / JDK 10+ 默认开启
-XX:+UseContainerSupport,无需额外加参数 - 设置容器内存 limit(如
docker run -m 1g),JVM 将自动把堆上限设为约 1/4(即 ~256m),行为可被-XX:MaxRAMPercentage调整 - 若需显式控制,用
-XX:MaxRAMPercentage=75.0,而非-Xmx768m—— 后者在不同容器配置下无法复用 - 禁用
-XX:+UseCGroupMemoryLimitForHeap(已废弃),它只在旧 JDK + cgroup v1 下生效,现代环境用UseContainerSupport即可
Spring Boot 应用在 Docker 中的健康检查配置
别依赖进程存活,Spring Boot Actuator 的 /actuator/health 才是真实就绪信号。
立即学习“Java免费学习笔记(深入)”;
- 在
application.yml中暴露端点:management: endpoints: web: exposure: include: health,info endpoint: health: show-details: when_authorized - Dockerfile 中添加健康检查:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/actuator/health || exit 1
- 确保容器内服务端口(如
8080)与EXPOSE一致,且 Spring Boot 未通过server.port改为其他值 - 若用非 root 用户启动(推荐),确认该用户有权限绑定端口(
server.port=8080没问题,80会失败)
--start-period 来容忍 Spring Boot 初始化延迟。










