在告诉您我将如何处理之前,我将解释您遇到的问题。
您的 Dockerfile 依赖于构建多阶段功能。
在这里,阶段被视为中间层,这些层不保留在最终图像中。要在图层之间保留文件/文件夹,您必须像完成的那样显式复制它们。
因此,具体来说,这意味着在下面的说明中:maven解析了pom中指定的所有依赖项.xml并将其存储在位于该阶段层的本地存储库中:
FROM maven:3.5-jdk-8 as mavenDeps
COPY pom.xml pom.xml
RUN mvn dependency:resolve
但如前所述,默认情况下不保留舞台内容。因此,本地 maven 存储库中所有下载的依赖项都将丢失,因为您永远不会在下一阶段复制它:
FROM mavenDeps as mavenBuild
RUN mvn install
由于该映像的本地存储库为空:重新下载所有依赖项。mvn install
如何加工?
你真的有很多很多方法。
最佳选择取决于您的要求。
但无论如何,就Docker层而言,构建策略如下所示:
构建阶段(Maven 图像):
- pom 复制到图像
- 依赖项和插件下载。
关于这一点,链接到可以完成工作,但并非总是如此。
为什么?因为这些插件和执行可能依赖于不同的工件/插件,甚至对于相同的工件/插件,这些可能仍然会拉出不同的版本。因此,一种更安全的方法虽然可能更慢,但通过精确执行命令(这将准确地拉取您需要的依赖项)来解决依赖项,但通过跳过源编译并删除目标文件夹以使处理速度更快并防止该步骤的任何不需要的层更改检测。mvn dependency:resolve-plugins
mvn dependency:resolve
package
mvn package
- 将源代码复制到映像
- 打包应用程序
运行阶段(JDK 或 JRE 图像):
1)没有对maven依赖关系的显式缓存:当pom频繁更改时,直接但很烦人
如果重新下载每个pom上的所有依赖项.xml更改是可以接受的。
从脚本开始的示例:
########build stage########
FROM maven:3.5-jdk-8 as maven_build
WORKDIR /app
COPY pom.xml .
# To resolve dependencies in a safe way (no re-download when the source code changes)
RUN mvn clean package -Dmaven.main.skip -Dmaven.test.skip && rm -r target
# To package the application
COPY src ./src
RUN mvn clean package -Dmaven.test.skip
########run stage########
FROM java:8
WORKDIR /app
COPY --from=maven_build /app/target/*.jar
#run the app
ENV JAVA_OPTS ""
CMD [ "bash", "-c", "java ${JAVA_OPTS} -jar *.jar -v"]
该解决方案的缺点 ?pom.xml中的任何更改都意味着重新创建下载并存储 maven 依赖项的整个层。
对于具有许多依赖项的应用程序,这通常是不可接受的,总体而言,如果您在映像构建期间不使用 maven 存储库管理器。
2)Maven依赖项的显式缓存:需要更多的配置和使用buildkit,但这更有效,因为只下载所需的依赖项
这里唯一变化的是maven依赖项下载缓存在docker构建器缓存中:
# syntax=docker/dockerfile:experimental
########build stage########
FROM maven:3.5-jdk-8 as maven_build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 mvn clean package -Dmaven.test.skip
########run stage########
FROM java:8
WORKDIR /app
COPY --from=maven_build /app/target/*.jar
#run the app
ENV JAVA_OPTS ""
CMD [ "bash", "-c", "java ${JAVA_OPTS} -jar *.jar -v"]
要启用buildkit,必须设置env变量(您可以在想要的地方执行此操作:bashrc,命令行,docker守护程序json文件...)DOCKER_BUILDKIT=1