多模块 Maven 项目和 Docker:找不到工件?

Multi Module Maven Project and Docker: Cannot find artifact?

我有以下多阶段 dockerfile 尝试复制我的多模块 java maven 项目的每个模块并使用 mvn clean install 构建我的 ear 文件。

docker文件:

# Copy files from local to maven image and build ear
FROM maven:3.5-jdk-8 AS build  
COPY module1 /usr/src/app/src  
COPY module2 /usr/src/app/src  
COPY module3 /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean install

# Create server image + rest of docker file (working ok)

我得到的错误如下:

Step 8/20 : RUN mvn -f /usr/src/app/pom.xml clean install
 ---> Running in cf9d8c1ef9ed
[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM for com.company.web:api:21.01-SNAPSHOT:
  Could not find artifact com.company.parent:jee6:pom:1.0.1-SNAPSHOT and
  'parent.relativePath' points at wrong local POM @ line 8, column 10
 @
[ERROR] The build could not read 1 project -> [Help 1]

pom.xml 中与此错误对应的部分:

<parent>
<groupId>com.company.parent</groupId>
<artifactId>jee6</artifactId>
<version>1.0.1-SNAPSHOT</version>
</parent>

我认为这个问题是因为当尝试 运行 Maven docker 图像中的命令时它看不到我的本地 .m2 文件夹?它正在寻找的依赖项是我本地机器上的私有依赖项。

复制我的 maven settings.xml 会有帮助吗?

我该如何解决这个问题?我不希望有人必须在他们的机器上安装 Maven 才能 运行 这个 docker 文件。

错误有 2 个不同的部分:找不到父元素,parent.relativePath 元素错误。我认为第二部分可能导致了第一部分。

由于您的父元素未指定 relativePath 元素,因此默认为模块父路径(又名 ..)。您的模块不在父文件夹 (/usr/src/app) 的子文件夹中,而是在 (/usr/src/app/src 子文件夹).

尝试将您的复制命令更改为:

COPY module1 /usr/src/app
COPY module2 /usr/src/app  
COPY module3 /usr/src/app  
COPY pom.xml /usr/src/app

然后您应该会看到:

/usr/src/app
/usr/src/app/module1
/usr/src/app/module2
/usr/src/app/module3

依赖项 com.company.parent:jee6:pom:1.0.1-SNAPSHOT 似乎是私有的,您在 Docker 构建中的 Maven 命令需要能够从私有存储库下载它或使其易于访问。

I assume this issue because when trying to run the command in the maven docker image it cannot see my local .m2 folder?

是的,它无法看到您的 settings.xml 私有存储库配置,或者如果它已经在本地可用,则无法看到本地依赖项。

Would also copying my maven settings.xml help?

最好不要:您的 settings.xml(以及其中最终的秘密)可能会被以后使用您的图片的任何人看到。使用带有 BuildKit 的秘密挂载将是一个更好的解决方案(见下文)


您有多个解决方案:

在构建期间将 settings.xml 装载为秘密

此解决方案假设您有 settings.xml configured with proper credentials to access private registry.

使用 Docker BuildKit with --mount=secretsettings.xml 加载为带有 Dockerfile 的秘密,例如:

# syntax=docker/dockerfile:1.2
# Required comment at top of Dockerfile for using BuildKit

FROM maven:3.5-jdk-8 AS build  

COPY module1 /usr/src/app/src  
COPY module2 /usr/src/app/src  
COPY module3 /usr/src/app/src  
COPY pom.xml /usr/src/app  

# Use your secret settings.xml
RUN --mount=type=secret,id=mvnsettings,target=/root/.m2/settings.xml \
  mvn -f /usr/src/app/pom.xml clean install

并构建命令如:

DOCKER_BUILDKIT=1 docker build --secret id=mvnsettings,src=$HOME/.m2/settings.xml . 

然后 Maven 应该能够在构建期间下载父依赖项。

注意:这不是 COPY 图片中的 settings.xml,因为秘密 settings.xml 仅可用于指定的构建步骤并赢得'被保留在最终图像中。

在构建期间复制 com.company.parent:jee6 pom.xml

此解决方案不太实用,可能无法完全解决问题:

  • 需要在构建上下文中提供 com.company.parent:jee6:pom:1.0.1-SNAPSHOT pom.xml 文件
  • 您的父级 pom.xml 可能引用了其他私有依赖项。您必须以相同的方式包含它们。

...但它仍然值得一试。

你可以这样做:

FROM maven:3.5-jdk-8 AS build  

# Copy and install parent pom
COPY parent-pom.xml /tmp/parent/pom.xml
RUN mvn -f /tmp/parent/pom.xml clean install

COPY module1 /usr/src/app/src  
COPY module2 /usr/src/app/src  
COPY module3 /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean install