How to build docker image with maven? - java

I have to build a docker image and package java application using maven in the docker container but when I run the build process all is going fine but all maven dependencies downloading from maven remote repo.
That is my docker file:
FROM ubuntu_img
CMD ./mvnw -s .mvn/settings.xml --batch-mode clean package
How can I configure docker or maven for downloading dependencies from maven local repository located on my laptop?

At first, you need to attach the directory of your existing local Maven repository into the Docker container:
VOLUME ["/home/<user>/.m2", "/root/.m2"]
Then you need to tell Maven (inside your container) to use this directory as a local repository.
setting.xml
<settings ...>
<localRepository>/root/.m2</localRepository>
...
</settings>

use volume,like this:
VOLUME ["/home/test/.m2", "/root/.m2"]

Related

Publishing/deploying artifacts to JFROG in multi module builds

I am working on a multi module project and trying to deploy them to JFROG.
Project Structure goes like this:
project
module-1
pom.xml
module-2
pom.xml
In the parent pom:
<modules>
module-1
module-2
<modules>
I have added <distributionManagement> and added the required details to connect to my artifactory.
Verified that there are no connectivity issues to Artifactory.
Module-1 gives com/abc/def/project/module-1/module-1.pom and com/abc/def/project/module-1/module-1.jar
Module-2 gives com/abc/def/project/module-2/module-2.pom and com/abc/def/project/module-2/module-2.jar
Requirement: I have to push the above pom and jar of both the sub modules to JFROG.
I am using goal - mvn clean deploy from my jenkins pipeline. However it is not working.
The best way to do that is to use the JFrog CLI. With that, you don't have to configure any resolution or deployment repositories in your pom.xml/settings.xml.
You can do that in 4 simple steps:
# Step 1: Install JFrog CLI
curl -fL https://install-cli.jfrog.io | sh
# Step 2: Configure the JFrog platform:
jf c add internal --url=https://acme.jfrog.io --user=jfrog_user --password=jfrog_password
# Step 3: Configure the Maven project
jf mvnc --repo-resolve-releases libs-release --repo-resolve-snapshots libs-snapshot --repo-deploy-snapshots libs-snapshot-local --repo-deploy-releases libs-release-local
# Step 4: Install and publish your Maven project
jf mvn clean install
Additionally, it is recommended to save the build-info in Artifactory.
To do that, set the JFROG_CLI_BUILD_NAME and JFROG_CLI_BUILD_NUMBER environment variables before step 4 and run jf rt build-publish in the end.
Read more:
QuickStart Guide: Maven and Gradle
Running Maven Builds
JFrog CLI Documentation

Multi Module Maven Project and Docker: Cannot find artifact?

I have the following multi-stage dockerfile that attempts to copy each module of my multi-module java maven project and build my ear file using mvn clean install.
dockerfile:
# 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)
The error that I am getting is as follows:
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]
The section in the pom.xml that corresponds to this error:
<parent>
<groupId>com.company.parent</groupId>
<artifactId>jee6</artifactId>
<version>1.0.1-SNAPSHOT</version>
</parent>
I assume this issue because when trying to run the command in the maven docker image it cannot see my local .m2 folder? And the dependency that it is looking for is a private dependency on my local machine.
Would also copying my maven settings.xml help?
How can I resolve this? I do not want someone to have to have Maven installed on their machine in order to run this dockerfile.
Dependency com.company.parent:jee6:pom:1.0.1-SNAPSHOT seems to be private, your Maven command inside Docker build needs to be able to either download it from private repository or have it readily accessible.
I assume this issue because when trying to run the command in the maven docker image it cannot see my local .m2 folder?
Yes, it then cannot see your settings.xml with private repository config, or local dependency if it's already available locally.
Would also copying my maven settings.xml help?
It's better not to: your settings.xml (and eventual secrets within) may be available to anyone using your image later. Using a secret mount with BuildKit would be a better solution (see below)
You have multiple solutions:
Mount settings.xml as secret during build
This solution assumes you have a settings.xml configured with proper credentials to access private registry.
Use Docker BuildKit with --mount=secret to load settings.xml as secret with a Dockerfile such as:
# 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
And build command such as:
DOCKER_BUILDKIT=1 docker build --secret id=mvnsettings,src=$HOME/.m2/settings.xml .
Maven should then be able to download parent dependency during build.
Note: this is NOT COPYing the settings.xml in image, as the secret settings.xml will only be made available for the specified build step and won't be persisted in final image.
Copy com.company.parent:jee6 pom.xml during build
This solution is less practical and may not solve problem entirely:
It would require to have com.company.parent:jee6:pom:1.0.1-SNAPSHOT pom.xml file available in build context
Your parent pom.xml may refer to other private dependencies. You would have to include them the same way.
... But it still may be worth a try.
You can do something like:
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
There are 2 different parts to the error: Cannot find the parent, and the parent.relativePath element is wrong. I think the 2nd part might be causing the 1st.
Since your parent element doesn't specify a relativePath element, the default is the module parent path (aka ..). Your modules are not in a child of the parent folder (/usr/src/app) but rather in the (/usr/src/app/src subfolder).
Try changing your copy commands to :
COPY module1 /usr/src/app
COPY module2 /usr/src/app
COPY module3 /usr/src/app
COPY pom.xml /usr/src/app
You should then see:
/usr/src/app
/usr/src/app/module1
/usr/src/app/module2
/usr/src/app/module3

Docker maven with dependency:go-offline not picking up local jars when built in docker image

In order to speed up our internal testing pipeline, I have decided to set up a docker image with pre-cached maven dependencies instead of them being downloaded in our pipeline each time.
We are using the mvn dependency:go-offline command during the docker process, and it is indeed downloading the local repository and being built into the image.
However, when we run our maven target from within the container when it is run I am seeing those same dependencies being re-downloaded. Is there a flag or something that I can use to ensure that maven first looks in the local repository?
You need to build with the -o flag.
See also: https://stackoverflow.com/a/7233762/927493
This allows you build offline without contacting the repositories.

How to deploy tools.jar into Nexus using Maven?

From the same directory I tried to deploy
spark-assembly-1.6.2.2.5.0.0-1245-hadoop2.7.3.2.5.0.0-1245.jar
and
tools.jar
(the later being a dependency of the first)
Despite launching the same commands:
mvn deploy:deploy-file -Dfile=./spark-assembly-1.6.2.2.5.0.0-1245-hadoop2.7.3.2.5.0.0-1245.jar -DgroupId="spark.yarn.jar" -DartifactId="spark-assembly-1.6.2.2.5.0.0-1245-hadoop2.7.3.2.5.0.0" -Dversion="1245-SNAPSHOT" -Dpackaging="jar" -DrepositoryId="stmms-id" -Durl="http://nexus.some.dns.com:8090/repository/maven-snapshots"
mvn deploy:deploy-file -Dfile=./tools.jar -DgroupId="jdk.tools" -DartifactId="jdk.tools" -Dversion="1.7.0_07" -Dpackaging="jar" -DrepositoryId="stmms-id" -Durl="http://nexus.some.dns.com:8090/repository/maven-snapshots"
the first is successfull but the second fails:
I also tried maven-deploy-plugin but with no much success.
Your repository maven-snapshots is a SNAPSHOT repository. You can only deploy SNAPSHOT versions to it.
So -Dversion="1245-SNAPSHOT" is ok, but -Dversion="1.7.0_07" is not.

maven deploying 3rd pom's without jar to nexus repository

When I want to deploy 3rd jars to my nexus 3 repository I use this command:
mvn deploy:deploy-file
-Dfile=<path-to-jar>
-DpomFile=<path-to-pom>
-DrepositoryId=<id-to-map-on-server-section-of-settings.xml>
-Durl=<url-of-the-repository-to-deploy>
but this command works only on jars with pom, and there is many artifacts that have only pom without jar, so i am looking for a way to deploy only pom without a jar file. My maven version is 3.3.9
mvn deploy:deploy-file
-DgroupId=com.xxx.xxx.xxxx
-DartifactId=xxxxx
-Dversion=x.x.x
-DgeneratePom=false
-DrepositoryId=nexus
-Dpackaging=pom
-Dfile=D:/xxx/xxxxx-x.x.x.pom
-DpomFile=D:/xxx/xxxxx-x.x.x.pom
-Durl=http://xxx.xx.xx.xx:8081/repository/thirdparty
-Dfile, is mandatory for Maven deploy-file. Therefore you have to specify a file.
In this case, you can point the same pom file for both -DpomFile and -Dfile.
This works in Nexus OSS version 3.23.0-03 with Maven 3.5.2

Categories