Dockerfile内解压Spring Boot fat jar后COPY提示路径不存在如何解决?
报错原因
CMD指令执行时机错误:CMD是容器启动时才会执行的命令,镜像构建阶段完全不会运行该指令,因此你写的解压逻辑在构建时没有执行,/build/dependencies目录下不存在任何解压后的文件。COPY指令规则理解错误:COPY的源路径默认指向宿主机的构建上下文路径,无法读取镜像内部生成的文件,镜像内部的文件操作需要使用RUN指令执行。- 缺少本地jar包复制步骤:调整后的Dockerfile没有先将本地构建好的fat jar复制到镜像内,就算解压命令能执行也找不到对应的jar文件。
修正方案
你可以选择单阶段构建方案,或者更推荐的多阶段构建方案(最终镜像体积更小、无冗余构建工具):
单阶段构建方案
FROM amazonlinux:2 # 安装运行和构建需要的依赖 RUN yum install -y java-11-amazon-corretto tar unzip procps ARG BUILD_VERSION ARG JAR_FILE=build/libs/payouts-spring-${BUILD_VERSION}.jar ARG DEPENDENCY=/build/dependencies # 复制本地fat jar到镜像内部 COPY ${JAR_FILE} /app/target/app.jar # 构建阶段执行解压,分层复制文件最大化利用缓存 RUN mkdir -p ${DEPENDENCY} \ && unzip -d ${DEPENDENCY} /app/target/app.jar \ # 先复制依赖层,依赖不变时缓存不会失效 && cp -r ${DEPENDENCY}/BOOT-INF/lib /app/lib \ && cp -r ${DEPENDENCY}/META-INF /app/META-INF \ # 最后复制业务代码层,代码变更仅重建该层 && cp -r ${DEPENDENCY}/BOOT-INF/classes /app \ # 清理无用文件减少镜像体积 && rm -rf ${DEPENDENCY} /app/target ENTRYPOINT ["java","-cp","app:app/lib/*","mypackage.MyApp"]
更推荐的多阶段构建方案
# 第一阶段:解压构建阶段,仅负责处理jar包 FROM amazonlinux:2 AS builder RUN yum install -y unzip ARG BUILD_VERSION ARG JAR_FILE=build/libs/payouts-spring-${BUILD_VERSION}.jar COPY ${JAR_FILE} /app.jar RUN mkdir -p /build/dependencies \ && unzip -d /build/dependencies /app.jar # 第二阶段:运行阶段,仅保留运行必需的组件 FROM amazonlinux:2 RUN yum install -y java-11-amazon-corretto procps # 从构建阶段直接复制分层后的文件 COPY --from=builder /build/dependencies/BOOT-INF/lib /app/lib COPY --from=builder /build/dependencies/META-INF /app/META-INF COPY --from=builder /build/dependencies/BOOT-INF/classes /app ENTRYPOINT ["java","-cp","app:app/lib/*","mypackage.MyApp"]
调整后你只需要先执行./gradlew jar构建出fat jar,再执行原来的docker build命令即可完成镜像构建,不需要再运行explodeJar任务。
内容的提问来源于stack exchange,提问作者MrkK
相关产品推荐
相关产品推荐

