最稳妥方案是用openjdk:17-jre-slim基础镜像,COPY JAR名须与java -jar一致,加-Djava.security.egd=file:/dev/./urandom防SecureRandom卡住,EXPOSE仅声明端口;配置优先用环境变量覆盖,如SERVER_PORT、SPRING_PROFILES_ACTIVE;构建推荐多阶段避免打包Maven;OOMKiller致退出码137需设JVM内存限制。

Java项目打成JAR包后怎么写Dockerfile
直接用 openjdk:17-jre-slim 基础镜像最稳妥,避免自己装JDK出错。关键不是“能不能跑”,而是“启动快不快、镜像小不小、日志输不输出”。
-
COPY的 JAR 文件名必须和java -jar命令里的一致,常见错误是写成app.jar但实际打包出来是myapp-1.0.0.jar - 加
-Djava.security.egd=file:/dev/./urandom防止 Spring Boot 启动卡在 SecureRandom 初始化(尤其在容器里熵池不足时) - 用
EXPOSE 8080只是声明,不自动开放端口;真正映射靠docker run -p 8080:8080
FROM openjdk:17-jre-slim
VOLUME /tmp
ARG JAR_FILE=target/myapp-1.0.0.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
如何让Spring Boot应用在Docker里正确读取配置
别把 application.yml 打进镜像——改个配置就得重构建。优先用环境变量覆盖,Spring Boot 原生支持 server.port → SERVER_PORT 这种映射。
- 数据库地址统一用
SPRING_DATASOURCE_URL,而不是硬编码在 yml 里 - 如果必须挂外部配置文件,用
docker run -v $(pwd)/config:/config+--spring.config.location=file:/config/ - 注意:
spring.profiles.active=prod对应环境变量是SPRING_PROFILES_ACTIVE=prod,大小写和下划线规则要对得上
Docker build时如何跳过Maven测试但保留编译
本地开发时你可能想快速验证容器启动逻辑,又不想等单元测试跑完。但直接 mvn package -Dmaven.test.skip=true 有风险:跳过测试 *也跳过测试编译*,万一主代码依赖了 test-util 类就编译失败。
- 安全做法是
mvn package -DskipTests:编译测试代码,但不执行 - 在 Dockerfile 中推荐分阶段构建,第一阶段用
maven:3.9-openjdk-17编译,第二阶段只拷target/*.jar到 JRE 镜像,避免把 Maven 和源码塞进最终镜像 - CI 场景下建议保留测试:用
mvn verify而不是package,否则容易漏掉集成问题
容器里Java进程退出码137是怎么回事
这是 OOM Killer 杀掉进程的典型信号,不是 Java 报错。Docker 默认不限制内存,但宿主机或 Kubernetes 会设 memory limit,而 JVM 不知道这个限制,按默认堆大小(比如 1/4 物理内存)申请,超限就被干掉。
立即学习“Java免费学习笔记(深入)”;
- 必须显式设置 JVM 堆上限:
java -Xmx512m -Xms512m -jar app.jar - 更可靠的是用 JVM 参数
-XX:+UseContainerSupport(JDK 10+ 默认开启),配合-XX:MaxRAMPercentage=75.0让 JVM 自动按容器内存 limit 算堆大小 - 验证是否生效:容器内执行
java -XX:+PrintFlagsFinal -version | grep MaxHeapSize,看输出值是否接近你设的 limit
Dockerfile,而在理解 JVM 和容器资源边界的耦合关系——比如 -Xmx 设大了会触发 OOMKiller,设小了又浪费资源;环境变量名拼错一个字母,Spring 就静默回退到默认配置,连报错都没有。










