Maven Parent Cache Offline

TL / DR: how can I cache the pom.xml file <parent> , so my build can be run offline?

I am using Docker to create a maven project. My goal is to add two steps to the build: one to load all the dependencies, and the other to create the project. This is what my Dockerfile looks like:

 FROM maven:3.3-jdk-8 # Download the project dependencies (so they can be cached by Docker) ADD pom.xml /runtime/ WORKDIR /runtime RUN mvn dependency:go-offline RUN mvn dependency:resolve-plugins # Mount the local repository ADD . /runtime # Build the service RUN mvn clean package -o -DskipTests 

This is similar to working with plugins. I checked /root/.m2/repository and everything seems to be in order.

Edit: double checking the /root/.m2/repository directory /root/.m2/repository longer exists. For some reason, Maven does not retain any dependencies on this location.

Edit 2: After creating the Docker image, there is no /root/.m2/repository directory. However, if I run mvn dependency:go-offline from inside the shell inside the Docker container, the directory is created without problems.

When I try to create my application, I get the following error:

 [ERROR] [ERROR] Some problems were encountered while processing the POMs: [FATAL] Non-resolvable parent POM for com.example:service:1.2: Cannot access central (http://jcenter.bintray.com) in offline mode and the artifact org.springframework.boot:spring-boot-starter-parent:pom:1.4.0.M3 has not been downloaded from it before. and 'parent.relativePath' points at wrong local POM @ line 14, column 13 @ [ERROR] The build could not read 1 project -> [Help 1] [ERROR] [ERROR] The project com.sample:service:1.2 (/runtime/pom.xml) has 1 error [ERROR] Non-resolvable parent POM for com.oe:graph-service:1.2: Cannot access central (http://jcenter.bintray.com) in offline mode and the artifact org.springframework.boot:spring-boot-starter-parent:pom:1.4.0.M3 has not been downloaded from it before. and 'parent.relativePath' points at wrong local POM @ line 14, column 13 -> [Help 2] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException [ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException 

The problem is that mvn dependency:go-offline does not allow parent. When I run the assembly offline, it breaks.

Here are the relevant parts of my pom.xml file:

 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> ... <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.M3</version> </parent> ... <repositories> <repository> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>bintray</name> <url>http://jcenter.bintray.com</url> </repository> <repository> <id>repository.springsource.snapshot</id> <name>SpringSource Snapshot Repository</name> <url>http://repo.springsource.org/snapshot</url> </repository> <repository> <id>spring-milestones</id> <url>http://repo.spring.io/milestone</url> </repository> </repositories> <dependencies> ... <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.scala</groupId> <artifactId>spring-scala_2.11</artifactId> <version>1.0.0.BUILD-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- disabling Spring cloud AWS until proper testing harnesses can be set up --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>LATEST</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-aws-autoconfigure</artifactId> <version>1.1.0.RELEASE</version> </dependency> ... </dependencies> ... </project> 
+5
source share
2 answers

If you configured the maven settings.xml file, you can save the repository files in the image.

Create a custom version of settings.xml , with the localRepository setting localRepository , for example:

 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <!-- localRepository | The path to the local repository maven will use to store artifacts. | | Default: ${user.home}/.m2/repository --> <localRepository>/usr/share/maven/repo</localRepository> ... 

Then override the default configuration when creating the image:

 FROM maven:3-jdk-8 COPY settings.xml /usr/share/maven/conf/settings.xml RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ADD . /usr/src/app RUN mvn dependency:go-offline RUN mvn clean package 

Your repository is now stored in /usr/share/maven/repo .

Using onbuild

You can also create a base image using ONBUILD , this will allow you to create custom images for each maven project.

Like this:

 FROM maven:3-jdk-8 COPY settings.xml /usr/share/maven/conf/settings.xml RUN mkdir -p /usr/src/app WORKDIR /usr/src/app ONBUILD ADD . /usr/src/app ONBUILD RUN mvn dependency:go-offline ONBUILD RUN mvn clean package 

Then create an image:

 docker build -t mvn_bldr . 

This will create a template for other maven images. Then you can create your own child image with:

 FROM mvn_bldr 

If you want to customize your image further, you can add additional instructions, each template instruction will be launched after the FROM mvn_bldr , as in the documents:

The trigger will execute in the context of the downstream assembly, as if it were inserted immediately after the FROM statement in the downstream Docker file.

+3
source

Using RUN with Docker might seem like running commands in a shell script, but it is not. Each RUN instance is applied to a new container, which is the result of the changes created by the previous command. Therefore, each command is executed within a new container context.

Dockers may contain a VOLUME link that mounts the external directory inside the Docker container. If there were files in the volume, these files are destroyed. Unless you explicitly specify volumes, Docker will be happy to create an empty folder instead.

As long as my Dockerfile does not contain an explicit reference to VOLUME , its parent does. So, although my mvn dependency:go-offline command was run, these files were destroyed in the next VOLUME step specified in the docker-maven Dockerfile .

In the end, I couldn't find a good way to make the Docker maven image, so I switched to the openjdk image and installed maven via apt-get instead.

+1
source

Source: https://habr.com/ru/post/1260610/


All Articles