Skip to content

Support system properties for Docker registries in Maven plugin #45253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- tag::docker-registry-global-settings[] -->
<profile>
<id>spring-boot-docker-creds</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring-boot.build-image.builder>my-custom/image-builder:1.0.0</spring-boot.build-image.builder>
<spring-boot.build-image.docker.builderRegistry.username>demo-user</spring-boot.build-image.docker.builderRegistry.username>
<spring-boot.build-image.docker.builderRegistry.email>demo-user@example.com</spring-boot.build-image.docker.builderRegistry.email>
<spring-boot.build-image.docker.builderRegistry.password>demo-user-password</spring-boot.build-image.docker.builderRegistry.password>
</properties>
</profile>
<!-- end::docker-registry-global-settings[] -->
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,24 @@ The following table summarizes the available parameters for `docker.builderRegis
|===
| Parameter | Description

| `username`
| `username` +
(`spring-boot.build-image.docker.[builderRegistry \| publishRegistry].username`)
| Username for the Docker image registry user. Required for user authentication.

| `password`
| `password` +
(`spring-boot.build-image.docker.[builderRegistry \| publishRegistry].password`)
| Password for the Docker image registry user. Required for user authentication.

| `url`
| `url` +
(`spring-boot.build-image.docker.[builderRegistry \| publishRegistry].url`)
| Address of the Docker image registry. Optional for user authentication.

| `email`
| `email` +
(`spring-boot.build-image.docker.[builderRegistry \| publishRegistry].email`)
| E-mail address for the Docker image registry user. Optional for user authentication.

| `token`
| `token` +
(`spring-boot.build-image.docker.[builderRegistry \| publishRegistry].token`)
| Identity token for the Docker image registry user. Required for token authentication.
|===

Expand Down Expand Up @@ -440,21 +445,13 @@ When using the `publish` option on the command line with authentication, you can
[source,shell]
----
$ mvn spring-boot:build-image \
-Ddocker.publishRegistry.username=user \
-Ddocker.publishRegistry.password=secret \
-Ddocker.publishRegistry.url=docker.example.com \
-Dspring-boot.build-image.docker.publishRegistry.username=user \
-Dspring-boot.build-image.docker.publishRegistry.password=secret \
-Dspring-boot.build-image.docker.publishRegistry.url=docker.example.com \
-Dspring-boot.build-image.publish=true \
-Dspring-boot.build-image.imageName=docker.example.com/library/my-app:v1
----

and reference the properties in the XML configuration:

[source,xml,indent=0,subs="verbatim,attributes"]
----
include::example$packaging-oci-image/docker-pom-authentication-command-line.xml[tags=docker]
----



[[build-image.examples.caches]]
=== Builder Cache and Workspace Configuration
Expand Down Expand Up @@ -555,3 +552,21 @@ If the builder or run image is stored in a private Docker registry that supports
----
include::example$packaging-oci-image/docker-token-authentication-pom.xml[tags=docker-token-authentication]
----

In addition to configuring credentials directly in the POM you can set these same credentials as system properties.

[source,shell]
----
$ mvn spring-boot:build-image \
-Dspring-boot.build-image.docker.builderRegistry.username=user \
-Dspring-boot.build-image.docker.builderRegistry.password=secret \
-Dspring-boot.build-image.docker.builderRegistry.url=docker.example.com \
----

Another option to externalizing credentials is to set the credentials in your global Maven `settings.xml` file.

[source,xml,indent=0,subs="verbatim,attributes"]
----
include::example$packaging-oci-image/docker-registry-global-settings.xml[tags=docker-registry-global-settings]
----

Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.springframework.boot.loader.tools.LayoutFactory;
import org.springframework.boot.loader.tools.Libraries;
import org.springframework.boot.loader.tools.LoaderImplementation;
import org.springframework.boot.maven.Docker.DockerRegistry;
import org.springframework.util.StringUtils;

/**
Expand Down Expand Up @@ -187,6 +188,86 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
@Parameter(property = "spring-boot.build-image.imagePlatform")
String imagePlatform;

/**
* Alias for the builder registry {@link DockerRegistry#username} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.builderRegistry.username")
String builderRegistryUsername;

/**
* Alias for the builder registry {@link DockerRegistry#password} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.builderRegistry.password")
String builderRegistryPassword;

/**
* Alias for the builder registry {@link DockerRegistry#username} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.builderRegistry.email")
String builderRegistryEmail;

/**
* Alias for the builder registry {@link DockerRegistry#token} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.builderRegistry.token")
String builderRegistryToken;

/**
* Alias for the builder registry {@link DockerRegistry#url} to support configuration
* through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.builderRegistry.url")
String builderRegistryUrl;

/**
* Alias for the publish registry {@link DockerRegistry#username} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.publishRegistry.username")
String publishRegistryUsername;

/**
* Alias for the publish registry {@link DockerRegistry#password} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.publishRegistry.password")
String publishRegistryPassword;

/**
* Alias for the publish registry {@link DockerRegistry#username} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.publishRegistry.email")
String publishRegistryEmail;

/**
* Alias for the publish registry {@link DockerRegistry#token} to support
* configuration through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.publishRegistry.token")
String publishRegistryToken;

/**
* Alias for the publish registry {@link DockerRegistry#url} to support configuration
* through command-line property.
* @since 3.5.0
*/
@Parameter(property = "spring-boot.build-image.docker.publishRegistry.url")
String publishRegistryUrl;

/**
* Docker configuration options.
* @since 2.4.0
Expand Down Expand Up @@ -262,9 +343,15 @@ private void buildImage() throws MojoExecutionException {
Libraries libraries = getLibraries(Collections.emptySet());
try {
BuildRequest request = getBuildRequest(libraries);
DockerConfiguration dockerConfiguration = (this.docker != null)
? this.docker.asDockerConfiguration(request.isPublish())
: new Docker().asDockerConfiguration(request.isPublish());
if (this.docker == null) {
this.docker = new Docker();
}
DockerRegistry builderRegistry = configureBuilderRegistry(this.docker.getBuilderRegistry());
DockerRegistry publisherRegistry = configurePublishRegistry(this.docker.getPublishRegistry());
this.docker.setBuilderRegistry(builderRegistry);
this.docker.setPublishRegistry(publisherRegistry);

DockerConfiguration dockerConfiguration = this.docker.asDockerConfiguration(request.isPublish());
Builder builder = new Builder(new MojoBuildLog(this::getLog), dockerConfiguration);
builder.build(request);
}
Expand All @@ -273,6 +360,40 @@ private void buildImage() throws MojoExecutionException {
}
}

private DockerRegistry configurePublishRegistry(DockerRegistry dockerRegistry) {
if (dockerRegistry == null) {
dockerRegistry = new DockerRegistry();
}
checkAndSetDockerRegistry(this.publishRegistryEmail, dockerRegistry.getEmail(), dockerRegistry::setEmail);
checkAndSetDockerRegistry(this.publishRegistryPassword, dockerRegistry.getPassword(),
dockerRegistry::setPassword);
checkAndSetDockerRegistry(this.publishRegistryToken, dockerRegistry.getToken(), dockerRegistry::setToken);
checkAndSetDockerRegistry(this.publishRegistryUrl, dockerRegistry.getUrl(), dockerRegistry::setUrl);
checkAndSetDockerRegistry(this.publishRegistryUsername, dockerRegistry.getUsername(),
dockerRegistry::setUsername);
return dockerRegistry;
}

private DockerRegistry configureBuilderRegistry(DockerRegistry dockerRegistry) {
if (dockerRegistry == null) {
dockerRegistry = new DockerRegistry();
}
checkAndSetDockerRegistry(this.builderRegistryEmail, dockerRegistry.getEmail(), dockerRegistry::setEmail);
checkAndSetDockerRegistry(this.builderRegistryPassword, dockerRegistry.getPassword(),
dockerRegistry::setPassword);
checkAndSetDockerRegistry(this.builderRegistryToken, dockerRegistry.getToken(), dockerRegistry::setToken);
checkAndSetDockerRegistry(this.builderRegistryUrl, dockerRegistry.getUrl(), dockerRegistry::setUrl);
checkAndSetDockerRegistry(this.builderRegistryUsername, dockerRegistry.getUsername(),
dockerRegistry::setUsername);
return dockerRegistry;
}

private void checkAndSetDockerRegistry(String value, String currentValue, Consumer<String> setter) {
if (StringUtils.hasText(value) && !StringUtils.hasText(currentValue)) {
setter.accept(value);
}
}

private BuildRequest getBuildRequest(Libraries libraries) {
ImagePackager imagePackager = new ImagePackager(getArchiveFile(), getBackupFile());
Function<Owner, TarArchive> content = (owner) -> getApplicationContent(owner, libraries, imagePackager);
Expand Down