Maven docker cache dependencies

2022-08-31 15:53:03

我正在尝试使用 Docker 来自动化 maven 构建。我想要构建的项目需要近20分钟才能下载所有依赖项,因此我尝试构建一个将缓存这些依赖项的docker映像,但它似乎没有保存它。我的 Dockerfile 是

FROM maven:alpine
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
ADD pom.xml /usr/src/app
RUN mvn dependency:go-offline

映像将生成,并且会下载所有内容。但是,生成的映像与基本映像的大小相同,因此它似乎没有缓存映像中的依赖项。当我尝试使用图像时,它会经历整整20分钟的重新下载所有内容。maven:alpinemvn compile

是否可以构建一个缓存我的依赖项的 maven 映像,以便它们不必在我每次使用该映像执行生成时都下载?

我正在运行以下命令:

docker build -t my-maven .

docker run -it --rm --name my-maven-project -v "$PWD":/usr/src/mymaven -w /usr/src/mymaven my-maven mvn compile

我的理解是,在 docker 构建过程中执行的任何操作都会成为生成的映像的一部分。RUN


答案 1

通常,当您尝试启动 Docker 映像构建时,文件中没有更改,但只有一些其他源代码更改。在这种情况下,您可以执行以下操作:pom.xml

仅供参考:

FROM maven:3-jdk-8

ENV HOME=/home/usr/app

RUN mkdir -p $HOME

WORKDIR $HOME

# 1. add pom.xml only here

ADD pom.xml $HOME

# 2. start downloading dependencies

RUN ["/usr/local/bin/mvn-entrypoint.sh", "mvn", "verify", "clean", "--fail-never"]

# 3. add all source code and start compiling

ADD . $HOME

RUN ["mvn", "package"]

EXPOSE 8005

CMD ["java", "-jar", "./target/dist.jar"]

所以关键是:

  1. 添加文件。pom.xml

  2. 然后,它将下载 maven 依赖项。mvn verify --fail-never

  3. 然后添加所有源文件,然后开始编译()。mvn package

当您的 pom.xml 文件发生更改或首次运行此脚本时,docker 将执行 1 -> 2 -> 3。当 pom.xml 文件没有变化时,docker 将跳过步骤 1、2 并直接执行 3。

这个简单的技巧可用于许多其他包装管理情况(渐变,纱线,npm,pip)。

编辑:

您还应该考虑使用或相应地使用其他评论和答案所建议。mvn dependency:resolvemvn dependency:go-offline


答案 2

使用 BuildKit

从现在开始,您可以使用BuildKit而不是其他答案中提到的卷。它允许挂载可以在构建之间保留的缓存,并且可以避免每次都下载相应内容。Docker v18.03.m2/repository

假设 Dockerfile 位于项目的根目录中:

# syntax = docker/dockerfile:1.0-experimental

FROM maven:3.6.0-jdk-11-slim AS build
COPY . /home/build
RUN mkdir /home/.m2
WORKDIR /home/.m2
USER root
RUN --mount=type=cache,target=/root/.m2 mvn -f /home/build/pom.xml clean compile

target=/root/.m2将缓存装载到 maven 映像 Dockerfile 文档中的指定位置。

对于构建,您可以运行以下命令:

DOCKER_BUILDKIT=1 docker build --rm --no-cache  .   

有关 BuildKit 的更多信息,请点击此处