问题
I want to cache Maven dependencies in a layer of the build stage of my Docker Multi Stage Build.
My Dockerfile looks as follows:
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
...
```
I based this Dockerfile on the example provided in the Docker Multi Stage Build blog post (also available on Github).
When I run the build, instead of seeing the dependencies downloaded once by dependency:resolve
and then re-used by package
, I am seeing the dependencies downloaded by both steps.
Has anyone got this working? What am I doing wrong here?
回答1:
I came across the same question. I found out it's due to differences between Maven targets (e.g. dependency:resolve
vs dependency:resolve-plugin
). Basically, dependency:resolve
is for application libraries, dependency:resolve-plugin
is for plugin libraries. Hence, libraries are downloaded in both RUN steps.
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
Even with dependency:resolve-plugins
, Maven will not download all required libraries as package
is a built-in target and requires additional libraries which dependency:resolve-plugin
won't know to resolve in the first RUN. I also tried dependency:go-offline
without success.
One solution is to run your build targets before and after adding your code to the build image. This will pull all the plugin dependencies into the lower layer allowing them to be re-used.
Applying this solution to your example above is as follows:
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
回答2:
I'd like to offer my two cents on this one.
I started with this 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
The goal is to not have any dependencies downloaded during the build step (which is mvn package
).
I tried to add the clean package
trick that is mentioned in the answer by @Apolozeus but this does not have an effect. In my case, I have surefire being downloaded during test and a mapstruct plugin being downloaded during compilation.
What I did in the end is to explicitly add these two plugins in my pom.xml
so that they will be downloaded early on:
<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>
This works and no further downloads happen during the build step, which speeds up the build.
来源:https://stackoverflow.com/questions/47969389/how-can-i-cache-maven-dependencies-and-plugins-in-a-docker-multi-stage-build-lay