Maven docker cache dependencies
Usually, there's no change in pom.xml
file but just some other source code changes when you're attempting to start docker image build. In such circumstance you can do this:
FYI:
FROM maven:3-jdk-8ENV HOME=/home/usr/appRUN mkdir -p $HOMEWORKDIR $HOME# 1. add pom.xml only hereADD pom.xml $HOME# 2. start downloading dependenciesRUN ["/usr/local/bin/mvn-entrypoint.sh", "mvn", "verify", "clean", "--fail-never"]# 3. add all source code and start compilingADD . $HOMERUN ["mvn", "package"]EXPOSE 8005CMD ["java", "-jar", "./target/dist.jar"]
So the key is:
add
pom.xml
file.then
mvn verify --fail-never
it, it will download maven dependencies.add all your source file then, and start your compilation(
mvn package
).
When there are changes in your pom.xml
file or you are running this script for the first time, docker will do 1 -> 2 -> 3. When there are no changes in pom.xml
file, docker will skip step 1、2 and do 3 directly.
This simple trick can be used in many other package management circumstances(gradle、yarn、npm、pip).
Edit:
You should also consider using mvn dependency:resolve
or mvn dependency:go-offline
accordingly as other comments & answers suggest.
It turns out the image I'm using as a base has a parent image which defines
VOLUME "$USER_HOME_DIR/.m2"
The result is that during the build, all the files are written to $USER_HOME_DIR/.m2
, but because it is expected to be a volume, none of those files are persisted with the container image.
Currently in Docker there isn't any way to unregister that volume definition, so it would be necessary to build a separate maven image, rather than use the official maven image.
Using BuildKit
From Docker v18.03
onwards you can use BuildKit instead of volumes that were mentioned in the other answers. It allows mounting caches that can persist between builds and you can avoid downloading contents of the corresponding .m2/repository
every time.
Assuming that the Dockerfile is in the root of your project:
# syntax = docker/dockerfile:1.0-experimentalFROM maven:3.6.0-jdk-11-slim AS buildCOPY . /home/buildRUN mkdir /home/.m2WORKDIR /home/.m2USER rootRUN --mount=type=cache,target=/root/.m2 mvn -f /home/build/pom.xml clean compile
target=/root/.m2
mounts cache to the specified place in maven image Dockerfile docs.
For building you can run the following command:
DOCKER_BUILDKIT=1 docker build --rm --no-cache .
More info on BuildKit can be found here.