如何在Docker Multi Stage Build Layer中缓存Maven依赖项和插件?

Tra*_*tle 5 build maven docker dockerfile docker-multi-stage-build

我想在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
...
Run Code Online (Sandbox Code Playgroud)

```

我基于Docker Multi Stage Build博客文章也在Github上提供)中提供的示例创建了该Dockerfile 。

当我运行构建时,没有看到一次下载了依赖项dependency:resolve,然后再重复使用package,而是看到了两个步骤都下载了依赖项。

有人有这个工作吗?我在这里做错了什么?

Apo*_*eus 6

我遇到了同样的问题。我发现这是由于Maven目标之间的差异(例如dependency:resolvevs dependency:resolve-plugin)造成的。基本上,dependency:resolve是用于应用程序库的,dependency:resolve-plugin是用于插件库的。因此,在两个RUN步骤中都下载了库。

dependency:resolve告诉Maven解决所有依赖关系并显示版本。JAVA 9注:与Java 9一起运行时,将显示模块名称。

dependency:resolve-plugins告诉Maven解析插件及其依赖项。

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
Run Code Online (Sandbox Code Playgroud)

  • 感谢上面的片段。唉,它不适用于最新的 Spring Boot 插件。Maven 抛出以下错误:`[ERROR] Failed to execute target org.springframework.boot:spring-boot-maven-plugin:2.0.3.RELEASE:repackage (default) on project core: Execution default of target org.springframework .boot:spring-boot-maven-plugin:2.0.3.RELEASE:repackage failed: Unable to find main class -> [Help 1]` 这是因为 Spring Boot 插件试图重新打包 JAR 文件并使其可执行。要修复该错误,您必须添加`-Dspring-boot.repackage.skip=true`。 (3认同)

Nik*_*iou 6

我想为这个出价两美分。

我从这个 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
Run Code Online (Sandbox Code Playgroud)

目标是在构建步骤(即mvn package)期间不下载任何依赖项。

我试图添加clean package@Apolozeus 在答案中提到的技巧,但这没有效果。就我而言,我在测试期间下载了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>
Run Code Online (Sandbox Code Playgroud)

这是有效的,并且在构建步骤期间不会发生进一步的下载,从而加快了构建速度。