spring-boot:build-image behind a proxy - spring

I'm trying to follow building a docker image with spring boot 2.3.0 from behind a proxy.
According to the docs https://docs.spring.io/spring-boot/docs/2.3.0.RELEASE/maven-plugin/reference/html/#build-image-example-builder-configuration I need something like
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
<configuration>
<image>
<env>
<HTTP_PROXY>http://proxy.example.com</HTTP_PROXY>
<HTTPS_PROXY>https://proxy.example.com</HTTPS_PROXY>
</env>
</image>
</configuration>
</plugin>
But I couldn't get that to work. However I could get it to work when prefixing the variables with BPL_ like below
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
<configuration>
<image>
<env>
<BPL_HTTP_PROXY>http://proxy.example.com</BPL_HTTP_PROXY>
<BPL_HTTPS_PROXY>https://proxy.example.com</BPL_HTTPS_PROXY>
</env>
</image>
</configuration>
</plugin>
So it this a bug, or something that I don't understand.
Even better, could this be specified outside the pom like from command line? I'm using powershell.

You are almost there, according to https://docs.spring.io/spring-boot/docs/2.5.6/maven-plugin/reference/htmlsingle/#build-image.examples.builder-configuration use HTTP_PROXY
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<env>
<HTTP_PROXY>http://some.proxy:3011</HTTP_PROXY>
<HTTPS_PROXY>http://some.proxy:3011</HTTPS_PROXY>
</env>
</image>
</configuration>
If you have the proxy is on your host and you want the build pack to use it, you can set <HTTP_PROXY>http://host.docker.internal:3011</HTTP_PROXY> and <HTTPS_PROXY>http://host.docker.internal:3011</HTTPS_PROXY> the host.docker.internal is the ip of the host machine for commands that are running inside the container

Related

Remove private docker registry credentials from Spring Boot POM file

I want to create docker images with CI/CD (Jenkins) of my spring boot application and push the image to a private nexus docker registry.
How to avoid adding my docker credentials to POM file and have them in GIT? Where should I pass/place the credentials instead?
Or should I just push the image manually in jenkins with docker login, docker push?
I followed this tutorial (https://docs.spring.io/spring-boot/docs/2.4.0/maven-plugin/reference/htmlsingle/#build-image-example-publish) and my POM looks like this:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>docker.example.com/library/${project.artifactId}</name>
<publish>true</publish>
</image>
<docker>
<publishRegistry>
<username>user</username>
<password>secret</password>
<url>https://docker.example.com/v1/</url>
<email>user#example.com</email>
</publishRegistry>
</docker>
</configuration>
</plugin>
</plugins>
</build>
</project>
You could use variables in your POM and pass them when calling maven. You should store the credentials in jenkins credentials manager
e.g.:
...
<properties>
<DOCKER_REGISTRY/>
<DOCKER_REGISTRY_USER/>
<DOCKER_REGISTRY_PASSWORD/>
<DOCKER_IMAGE_NAME>${DOCKER_REGISTRY}/${project.artifactId}:${project.version}</DOCKER_IMAGE_NAME>
</properties>
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>${DOCKER_IMAGE_NAME}</name>
<publish>true</publish>
</image>
<docker>
<publishRegistry>
<username>${DOCKER_REGISTRY_USER}</username>
<password>${DOCKER_REGISTRY_PASSWORD}</password>
<url>${DOCKER_REGISTRY}</url>
</publishRegistry>
</docker>
</configuration>
</plugin>
...
Then you could call maven like this in your jenkins pipeline:
stage('Build Docker Image') {
steps {
withCredentials([usernamePassword(credentialsId: 'YOUR_CREDENTIALS_ID', passwordVariable: 'NEXUS_PASSWORD', usernameVariable: 'NEXUS_USER')]) {
sh "mvn -DskipTests=true spring-boot:build-image -DDOCKER_REGISTRY=SUBDOMAIN.DOMAIN.COM -DDOCKER_REGISTRY_USER=$NEXUS_USER -DDOCKER_REGISTRY_PASSWORD=$NEXUS_PASSWORD"
}
}
}
You can store the credentials using Jenkins credential manager, and set them up in your mvn build command via -D parameters

Pass dockerPublisher maven properties over command line in spring-boot:build-image

I want to integrate the spring boot maven plugins capability to build and publish an OCI Image to a remote Repository
My Goal
I want to use the following plugin configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>${docker.image.prefix}/${project.artifactId}:${project.version}</name>
</image>
</configuration>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
</plugin>
And now I want to pass the docker.publishRegistry variables by command line.
What I've tried so far
I've tried to pass the parameter with the -Ddocker.publishRegistry.username property but that didn't work.
When you take a look at the source code of the plugin Docker has no Parameter property assigned to it:
/**
* Alias for {#link Image#publish} to support configuration via command-line property.
*/
#Parameter(property = "spring-boot.build-image.publish", readonly = true)
Boolean publish;
/**
* Docker configuration options.
* #since 2.4.0
*/
#Parameter
private Docker docker;
https://github.com/spring-projects/spring-boot/blob/82b90d57496ba85be316b9eb88a36d81f2cc9baa/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java#L159
So I guess it is not possible to define this parameter by command line or is it?
Current Workaround
Currently I'm defining the properties by global maven properties and reuse them in the docker scope.
My pom.xml:
<properties>
<docker-registry>https://example.org</docker-registry>
<docker-registry-username>username</docker-registry-username>
<docker-registry-username>password</docker-registry-username>
</properties>
<!-- ... -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>${docker.image.prefix}/${project.artifactId}:${project.version}</name>
</image>
<docker>
<publishRegistry>
<username>${docker-registry-username}</username>
<password>${docker-registry-password}</password>
<url>${docker-registry}</url>
</publishRegistry>
</docker>
</configuration>
<executions>
<execution>
<goals>
<goal>build-image</goal>
</goals>
</execution>
</executions>
</plugin>
And I'm building with:
./mvnw -B -s \
-Dspring-boot.build-image.publish=true \
-Ddocker-registry-username="$USERNAME" \
-Ddocker-registry-password="$PASSWORD" \
-Ddocker-registry="$REGISTRY" \
clean deploy
I have not the exact solution to you question: "passing publishRegistry parameters on the command line", but If I may, I have another workaround that shields you from exposing your credential in the pom.xml.
What i have done is to put the parameters and credential in a profile in my .m2/settings.xml like this:
<profiles>
<profile>
<id>docker-io-credentials</id>
<properties>
<docker-reg>docker.io</docker-reg>
<docker-reg.user>your-user-name</docker-reg.user>
<docker-reg.pwd>your-token-or-passwd</docker-reg.pwd>
<docker-reg.url>${docker-reg}/library/${docker-reg.user}</docker-reg.url>
</properties>
</profile>
</profiles>
Then on the command-line you can simply pass the profile's name to merge the credential to the current build.
mvn clean install -Pdocker-io-credentials
You can define placeholders in the spring-boot plugin's configuration, which refer to environment variables. This will be slightly less complex, so like
...
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>main.Class</mainClass>
<image>
<name>registry-url/library/image-name:${project.version}</name>
</image>
<docker>
<publishRegistry>
<username>docker-user</username>
<password>${env.docker_registry_password}</password>
<url>https://registry-url/v1/</url>
<email>user#example.com</email>
</publishRegistry>
</docker>
</configuration>
...
See more on this topic here: https://www.baeldung.com/maven-env-variables
Just to mention that the Spring team is aware and did not consider this a bug but rather a documentation issue: https://github.com/spring-projects/spring-boot/issues/31024#issuecomment-1127905504
Very similar to what #twobiers suggested in his workaround:
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<docker>
<publishRegistry>
<url>${docker.publishRegistry.url}</url>
<username>${docker.publishRegistry.username}</username>
<password>${docker.publishRegistry.password}</password>
</publishRegistry>
</docker>
</configuration>
and then I build (and publish to Github Packages Registry) my project with:
./mvnw spring-boot:build-image \
-Ddocker.publishRegistry.username=${{ github.actor }} \
-Ddocker.publishRegistry.password=${{ secrets.GITHUB_TOKEN }} \
-Ddocker.publishRegistry.url=ghcr.io \
-Dspring-boot.build-image.publish=true \
-Dspring-boot.build-image.imageName="ghcr.io/${{ github.repository }}:latest" \
-DskipTests

volumes in docker-maven-plugin not binding

I am using docker-maven-plugin to run an image from a remote repository.
The image is running using docker:start but it seems like the volumes not working.
I run the command using groovy (jenkins):
sh(script:"mvn -B -gs ${cfg} -f lib/pom.xml docker:start", returnStatus: true)
my pom.xml code is:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.31.0</version>
<configuration>
<images>
<image>
<name>imageName:latest</name>
<run>
<volumes>
<bind>
<volume>/inputs:/inputs</volume>
<volume>/out:/out</volume>
<volume>/env:/env</volume>
</bind>
</volumes>
</run>
</image>
</images>
</configuration>
</plugin>
any idea what is going wrong?

Docker image not getting image name from pom.xml

I am creating the docker image using spotify. My docker image is creating successfully but w/o a name. I am getting below on console:
Image will be built without a name
POM.XML
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.nv</groupId>
<artifactId>microeurekaserver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>MicroEurekaServer</name>
<description>Eureka Server</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR2</spring-cloud.version>
<docker.image.prefix>nvarshney44/nvarshney</docker.image.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<forceTags>true</forceTags>
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<serverId>docker-hub</serverId>
<registryUrl>https://index.docker.io/v1/</registryUrl>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Please help me out whats wrong with it. In maven output it is showing dockerfile:null may be it is costing some issue.
In order to give a Docker image a name, you need to fill in the "repository" field:
<configuration>
<repository>your-name-here</repository> <!-- ${project.artifactId} is a good choice -->
<tag>${project.version}</tag>
</configuration>
This is actually consistent with the way Docker push works - it treats the name as the repository address.
Where are you defining this variables values ${docker} and ${project}?
It's gonna be something like:
<docker>
<image>
<prefix>
value
</prefix>
</image>
</docker>
Please check: Using variables in pom.xml

How can I use properties exactly as they are provided by the io.fabric8 docker-maven-plugin?

Maven properties filled in by io.fabric8 docker-maven-plugin seem not to be interpolated when used as is.
The docker-maven-plugin fills in some maven properties (some.host and some.port) which I try to resolve.
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.15.5</version>
<configuration>
<images>
<image>
<alias>...</alias>
<name>...</name>
<run>
<ports>
<port>+some.host:some.port:5432</port>
</ports>
<namingStrategy>alias</namingStrategy>
</run>
</image>
</images>
</configuration>
</plugin>
They are used like this:
<properties>
<docker.host>${some.host}</docker.host>
<docker.port>${some.port}</docker.port>
</properties>
which leads to two empty values. They contain nothing while they should contain e.g. 127.0.0.1 and 5555.
If I add some characters, suddenly the values are interpolated correctly (but of course the values are useless then)
<properties>
<docker.host>${some.host}+abc</docker.host>
<docker.port>${some.port}+123</docker.port>
</properties>
which leads to 127.0.0.1+abc and 5555+123
Some things I tried don't work either:
<properties>
<dollar>$</dollar>
<docker.host>${dollar}{some.host}</docker.host>
<docker.port>${some.port}${}</docker.port>
</properties>
which leads to an empty value and 5555null
Roland Huß noted that the problem could be avoided by using dockers fixed ports. And that should be the first choice.
But for completion, I'll add a solution that also works:
Trick maven into creating an empty property (e.g., using the groovy-maven-plugin)
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>groovy-maven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>set empty property</id>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
<![CDATA[
project.properties.setProperty('empty', '');
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
Use the empty property to make maven interpolate the properties exposed by the docker-maven-plugin
<docker.host>${some.host}${empty}</docker.host>
<docker.port>${some.port}${empty}</docker.port>

Resources