Docker 部署 Java 服务,表面上只是把 java -jar 放进镜像里。真正要跑稳,需要处理镜像层、运行参数、配置注入、日志输出、健康检查和资源限制。
如果这些边界没分清,容器只是把原来的部署问题包了一层壳。
镜像只放运行必需内容
一个简单的 Java 服务 Dockerfile 可以这样:
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/app.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
生产镜像尽量只放运行需要的 JRE、应用包和必要脚本。不要把源码、构建缓存、本地配置和密钥打进镜像。
构建阶段和运行阶段可以分开。复杂项目可以用多阶段构建,减少最终镜像体积。
配置通过环境或挂载注入
不同环境的数据库地址、Redis 地址、日志级别、外部接口地址都不应该写死在镜像里。
常见方式有:
- 环境变量
- 配置文件挂载
- 配置中心
- 启动参数
例如:
docker run \
-e SPRING_PROFILES_ACTIVE=prod \
-e JAVA_OPTS="-Xms512m -Xmx512m" \
app:latest
镜像应该是同一个,环境差异通过配置注入。
日志优先输出到 stdout
容器化服务推荐把日志输出到标准输出,由 Docker、Kubernetes 或日志采集系统统一处理。
如果仍然写文件,要明确:
- 文件目录是否挂载。
- 是否有滚动策略。
- 容器删除后日志是否还在。
- 日志采集能否读到。
最怕的是服务在容器里写本地文件,外部没有采集,容器重建后排障现场直接丢失。
健康检查要有真实语义
Java 服务最好提供健康检查接口:
GET /actuator/health
健康检查不要只返回进程活着,还要区分服务是否真正可用。比如核心依赖不可用时,是否应该从负载均衡摘除,要按业务场景判断。
Docker 或编排平台可以基于健康检查决定重启、摘流或告警。
实用结论
Docker 部署 Java 服务的关键不是把 JAR 塞进容器,而是明确镜像、配置、日志、健康检查和资源限制的边界。
镜像保持纯净,配置外置,日志可采集,健康检查有语义,服务才算真正容器化。否则只是把传统部署问题搬进了容器。
正文完




