如果我们在 dockerfile 中使用 CMD,Docker 多阶段构建会失败

Gok*_*ica 2 java maven docker dockerfile docker-multi-stage-build

Dockerfile:

FROM maven:3.6.3-openjdk-8 as builder
# Set the working directory.
WORKDIR /usr/src/mymaven
COPY ./ /usr/src/mymaven
CMD [ "mvn" , "clean" , "install" ]

FROM openjdk:8
COPY --from=builder /usr/src/mymaven/target /usr/src/myapp
WORKDIR /usr/src/myapp
CMD ["java", "-jar" , "Backend-0.0.1-SNAPSHOT.jar"]
Run Code Online (Sandbox Code Playgroud)

上面的 docker build 失败并显示错误:目标文件夹不存在
下面的 dockerfile 完美运行:

FROM maven:3.6.3-openjdk-8 as builder
# Set the working directory.
WORKDIR /usr/src/mymaven
COPY ./ /usr/src/mymaven
RUN [ "mvn" , "clean" , "install" ]

FROM openjdk:8
COPY --from=builder /usr/src/mymaven/target /usr/src/myapp
WORKDIR /usr/src/myapp
CMD ["java", "-jar" , "Backend-0.0.1-SNAPSHOT.jar"]
Run Code Online (Sandbox Code Playgroud)

只需将 CMD 更改为 RUN 即可解决问题。为什么会这样?我认为在间歇性容器中,cmd 将执行这应该使两个命令等效,对吗?

leo*_*pal 5

在多阶段构建中,您可以从上一步复制文件。每个步骤都被视为一个单独的私有映像(在多阶段构建的范围内)。

CMD然而,指令不会在构建时调用,它只适用于运行时,如官方文档中明确所述:

CMD 的主要目的是为正在执行的容器提供默认值。

由于您当前正在构建结果图像,CMD因此永远不会执行,因此您会收到您报告的错误。

另一方面,RUN指令在构建期间执行,使其结果可用于下一步。再次引用文档

RUN 指令将在当前图像之上的新层中执行任何命令并提交结果。生成的提交映像将用于 Dockerfile 中的下一步。

现在应该清楚为什么多阶段构建RUN在与CMD指令相反的情况下成功完成。

您的困惑始于错误地假设以下内容为真:

我认为在间歇性容器中,cmd 将执行这应该使两个命令等效,对吗?