
Docker 多阶段构建时,若第二阶段未通过 COPY --from=build 正确引用前一构建阶段的产物(如 target/ 目录),会导致生成的镜像中缺少 JAR 文件,进而使应用无法启动。本文详解正确配置方式及常见陷阱。
如何修复 docker 多阶段构建中目标文件夹缺失的问题?docker 多阶段构建时,若第二阶段未通过 copy --from=build 正确引用前一构建阶段的产物(如 target/ 目录),会导致生成的镜像中缺少 jar 文件,进而使应用无法启动。本文详解正确配置方式及常见陷阱。
在使用多阶段构建(multi-stage build)打包 Java 应用时,一个典型错误是:误将 COPY ./target ./ 理解为从第一阶段复制产物,实则它默认从宿主机(host)路径拷贝——而宿主机上很可能根本不存在 ./target 目录,导致 ENTRYPOINT 启动失败,报错 “target folder is missing”。
正确的做法是显式指定源阶段(stage)和其内部绝对路径。以下是修正后的完整 Dockerfile:
FROM maven:3.9.3-amazoncorretto-20 AS build WORKDIR /usr/src/app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests FROM amazoncorretto:20-alpine-jdk WORKDIR /app # ✅ 关键修正:使用 --from=build 并指定构建阶段内的绝对路径 COPY --from=build /usr/src/app/target/*.jar app.jar COPY entrypoint.sh . RUN chmod +x entrypoint.sh CMD ["./entrypoint.sh"]
? 为什么原写法失效?
COPY ./target ./中的./target是构建上下文中的本地路径,与build阶段完全无关;- Docker 不会自动跨阶段共享文件系统,必须显式用
--from=<stage-name></stage-name>声明来源;- 若启用 BuildKit(Docker 23.0+ 默认),Docker 甚至可能跳过未被引用的构建阶段(如你的
build阶段),直接导致mvn package根本不执行。
✅ 最佳实践建议:
- 始终为构建阶段命名(如
AS build),并在后续COPY --from=中准确引用; - 使用
WORKDIR统一路径上下文,避免相对路径歧义; - 推荐精确复制生成的 JAR(如
*.jar)而非整个target/目录,减小镜像体积; -
ENTRYPOINT改为CMD(配合shell形式或exec形式),更符合 Docker 最佳实践;若需ENTRYPOINT,请确保entrypoint.sh具有可执行权限(RUN chmod +x)并以#!/bin/sh开头。
最后验证构建结果:
docker build -t my-java-app . docker run --rm my-java-app ls -l /app/ # 应能看到 app.jar 和 entrypoint.sh
遵循以上结构,即可确保 Maven 构建产物可靠传递至运行阶段,彻底解决 “target folder is missing” 问题。











