如何在 Docker 多阶段构建层中缓存 Maven 依赖项和插件?
How can I cache Maven dependencies and plugins in a Docker Multi Stage Build Layer?
我想在 Docker Multi Stage Build 的构建阶段缓存 Maven 依赖项。
我的 Dockerfile 如下所示:
FROM maven:3-jdk-8 as mvnbuild
RUN mkdir -p /opt/workspace
WORKDIR /opt/workspace
COPY pom.xml .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml dependency:resolve
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package
FROM openjdk:8-jre-alpine
...
```
我将此 Dockerfile 基于 Docker Multi Stage Build blog post (also available on Github).
中提供的示例
当我 运行 构建时,我没有看到依赖项被 dependency:resolve
下载一次然后被 package
重新使用,而是看到两个步骤都下载了依赖项。
有人成功了吗?我在这里做错了什么?
我遇到了同样的问题。我发现这是由于 Maven 目标之间的差异(例如 dependency:resolve
与 dependency:resolve-plugin
)。基本上,dependency:resolve
用于应用程序库,dependency:resolve-plugin
用于插件库。因此,库在 运行 两个步骤中下载。
dependency:resolve tells Maven to resolve all dependencies and
displays the version. JAVA 9 NOTE: will display the module name when
running with Java 9.
dependency:resolve-plugins tells Maven to resolve
plugins and their dependencies.
https://maven.apache.org/plugins/maven-dependency-plugin/index.html
即使使用 dependency:resolve-plugins
,Maven 也不会下载所有必需的库,因为 package
是一个内置目标,并且需要 dependency:resolve-plugin
不知道要在首先运行。我也试过 dependency:go-offline
没有成功。
一个解决方案是 运行 在将代码添加到构建映像之前和之后的构建目标。这会将所有插件依赖项拉入下层,以便重新使用它们。
将此解决方案应用于上面的示例如下:
FROM maven:3-jdk-8 as mvnbuild
RUN mkdir -p /opt/workspace
WORKDIR /opt/workspace
COPY pom.xml .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml dependency:resolve-plugins dependency:resolve clean package
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml clean package
FROM openjdk:8-jre-alpine
我愿意为此付出两分钱。
我从这个 Dockerfile 开始:
FROM maven:3-jdk-10 AS build
RUN mkdir /src
WORKDIR /src
COPY pom.xml .
RUN mvn -B dependency:resolve-plugins dependency:resolve
COPY . .
RUN mvn package
目标是在构建步骤(mvn package
)期间不下载任何依赖项。
我试图添加@Apolozeus 在回答中提到的 clean package
技巧,但这没有效果。就我而言,我在测试期间下载了 surefire,在编译期间下载了一个 mapstruct 插件。
我最后做的是在我的 pom.xml
中显式添加这两个插件,以便它们可以早点下载:
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit4</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
<scope>compile</scope>
</dependency>
这有效,并且在构建步骤期间不会发生进一步的下载,从而加快了构建速度。
我想在 Docker Multi Stage Build 的构建阶段缓存 Maven 依赖项。
我的 Dockerfile 如下所示:
FROM maven:3-jdk-8 as mvnbuild
RUN mkdir -p /opt/workspace
WORKDIR /opt/workspace
COPY pom.xml .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml dependency:resolve
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml package
FROM openjdk:8-jre-alpine
...
```
我将此 Dockerfile 基于 Docker Multi Stage Build blog post (also available on Github).
中提供的示例当我 运行 构建时,我没有看到依赖项被 dependency:resolve
下载一次然后被 package
重新使用,而是看到两个步骤都下载了依赖项。
有人成功了吗?我在这里做错了什么?
我遇到了同样的问题。我发现这是由于 Maven 目标之间的差异(例如 dependency:resolve
与 dependency:resolve-plugin
)。基本上,dependency:resolve
用于应用程序库,dependency:resolve-plugin
用于插件库。因此,库在 运行 两个步骤中下载。
dependency:resolve tells Maven to resolve all dependencies and displays the version. JAVA 9 NOTE: will display the module name when running with Java 9.
dependency:resolve-plugins tells Maven to resolve plugins and their dependencies.
https://maven.apache.org/plugins/maven-dependency-plugin/index.html
即使使用 dependency:resolve-plugins
,Maven 也不会下载所有必需的库,因为 package
是一个内置目标,并且需要 dependency:resolve-plugin
不知道要在首先运行。我也试过 dependency:go-offline
没有成功。
一个解决方案是 运行 在将代码添加到构建映像之前和之后的构建目标。这会将所有插件依赖项拉入下层,以便重新使用它们。
将此解决方案应用于上面的示例如下:
FROM maven:3-jdk-8 as mvnbuild
RUN mkdir -p /opt/workspace
WORKDIR /opt/workspace
COPY pom.xml .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml dependency:resolve-plugins dependency:resolve clean package
COPY . .
RUN mvn -B -s /usr/share/maven/ref/settings-docker.xml clean package
FROM openjdk:8-jre-alpine
我愿意为此付出两分钱。
我从这个 Dockerfile 开始:
FROM maven:3-jdk-10 AS build
RUN mkdir /src
WORKDIR /src
COPY pom.xml .
RUN mvn -B dependency:resolve-plugins dependency:resolve
COPY . .
RUN mvn package
目标是在构建步骤(mvn package
)期间不下载任何依赖项。
我试图添加@Apolozeus 在回答中提到的 clean package
技巧,但这没有效果。就我而言,我在测试期间下载了 surefire,在编译期间下载了一个 mapstruct 插件。
我最后做的是在我的 pom.xml
中显式添加这两个插件,以便它们可以早点下载:
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit4</artifactId>
<version>2.21.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
<scope>compile</scope>
</dependency>
这有效,并且在构建步骤期间不会发生进一步的下载,从而加快了构建速度。