Maven父子微服务项目Docker构建时父POM无法解析问题求助
我正在开发微服务项目,父项目obshaga仅包含pom.xml和子模块(微服务)。为便于部署,计划使用docker-compose,因此在每个子项目中编写了Dockerfile,例如微服务tg-dispatcher中的Dockerfile如下:
FROM openjdk:11 as build WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ COPY src ./src RUN ["./mvnw", "install"] ENTRYPOINT ["java", "-jar", "./target/tg-dispatcher.jar"]
父项目obshaga的pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project ...> <modelVersion>4.0.0</modelVersion> <groupId>org.dompurrr</groupId> <artifactId>obshaga</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>tg-dispatcher</module> <module>node</module> </modules> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <telegrambot.starter.version>6.1.0</telegrambot.starter.version> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.2</version> </parent> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>3.9.1.2184</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.4</version> <executions> <execution> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <reportFormat>plain</reportFormat> <includes> <include>**/*Test*.java</include> <include>**/*IT*.java</include> </includes> </configuration> </plugin> </plugins> </build> </project>
子项目tg-dispatcher的pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project ...> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.dompurrr</groupId> <artifactId>obshaga</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>tg-dispatcher</artifactId> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.telegram</groupId> <artifactId>telegrambots-spring-boot-starter</artifactId> <version>${telegrambot.starter.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> </dependencies> <build> <finalName>tg-dispatcher</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
构建tg-dispatcher的Docker镜像时出现如下错误:
[FATAL] Non-resolvable parent POM for org.dompurrr:tg-dispatcher:1.0-SNAPSHOT: Could not find artifact org.dompurrr:obshaga:pom:1.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 6, column 13 @ [ERROR] The build could not read 1 project -> [Help 1] [ERROR] [ERROR] The project org.dompurrr:tg-dispatcher:1.0-SNAPSHOT (/app/pom.xml) has 1 error [ERROR] Non-resolvable parent POM for org.dompurrr:tg-dispatcher:1.0-SNAPSHOT: Could not find artifact org.dompurrr:obshaga:pom:1.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 6, column 13 -> [Help 2]
本地执行maven package或maven install均可正常构建,但在Docker内构建时出现问题。不想将父项目构件部署到Maven中央仓库,请问是否有在Docker内本地部署父构件的方法,或其他解决方案?比如是否可以重构项目,让每个微服务不再依赖父项目?
方案1:修改Dockerfile,先安装父项目POM到本地仓库
问题根源是Docker构建上下文仅包含子项目文件,父项目POM不在构建环境中,导致Maven无法解析父依赖。可以调整Dockerfile,从父项目目录构建,或复制父项目POM到容器中先安装:
假设项目结构为:
obshaga/ ├── pom.xml ├── tg-dispatcher/ │ ├── pom.xml │ ├── src/ │ └── Dockerfile └── node/
修改tg-dispatcher/Dockerfile如下:
FROM openjdk:11 as build WORKDIR /app # 复制父项目POM并安装到本地Maven仓库 COPY ../pom.xml ../pom.xml RUN cd .. && ./mvnw install -DskipTests # 复制子项目文件并构建 COPY .mvn/ .mvn COPY mvnw pom.xml ./ COPY src ./src RUN ./mvnw install -DskipTests ENTRYPOINT ["java", "-jar", "./target/tg-dispatcher.jar"]
执行构建时需在父项目目录下运行:docker build -f tg-dispatcher/Dockerfile .,确保构建上下文包含父项目文件。
方案2:在子项目POM中指定父项目相对路径
在子项目tg-dispatcher/pom.xml的<parent>节点中添加relativePath属性,指向父项目POM,让Maven优先从本地路径查找:
<parent> <groupId>org.dompurrr</groupId> <artifactId>obshaga</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent>
同时修改Dockerfile,确保父项目POM被复制到构建环境:
FROM openjdk:11 as build WORKDIR /app # 复制父项目POM到子项目的上级目录 COPY ../pom.xml ../pom.xml COPY .mvn/ .mvn COPY mvnw pom.xml ./ COPY src ./src RUN ["./mvnw", "install"] ENTRYPOINT ["java", "-jar", "./target/tg-dispatcher.jar"]
同样需要在父项目目录下执行构建命令。
方案3:移除父子项目依赖,独立每个微服务
如果不想维护父子项目结构,可将父项目中的配置、依赖全部迁移到子项目,让每个微服务成为独立Maven项目:
- 在
tg-dispatcher/pom.xml中替换父依赖为Spring Boot官方父项目:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.2</version> </parent>
- 复制父项目的
<properties>、<dependencies>、<build>配置到子项目pom.xml:
<properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <telegrambot.starter.version>6.1.0</telegrambot.starter.version> </properties> <dependencies> <!-- 父项目原有依赖 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <scope>provided</scope> </dependency> <!-- 子项目原有依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.telegram</groupId> <artifactId>telegrambots-spring-boot-starter</artifactId> <version>${telegrambot.starter.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> </dependencies> <build> <finalName>tg-dispatcher</finalName> <plugins> <!-- 父项目原有构建插件 --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.4</version> <executions> <execution> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <reportFormat>plain</reportFormat> <includes> <include>**/*Test*.java</include> <include>**/*IT*.java</include> </includes> </configuration> </plugin> <!-- 子项目原有插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
修改后子项目不再依赖父项目,原有Dockerfile无需改动,直接在子项目目录下构建即可。
内容的提问来源于stack exchange,提问作者Deonisiy

