diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/examples/packaging-oci-image/docker-pom-authentication-command-line.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/examples/packaging-oci-image/docker-pom-authentication-command-line.xml deleted file mode 100644 index fd688ea0b237..000000000000 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/examples/packaging-oci-image/docker-pom-authentication-command-line.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - ${docker.publishRegistry.url} - ${docker.publishRegistry.username} - ${docker.publishRegistry.password} - - - - - - - - \ No newline at end of file diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/examples/packaging-oci-image/docker-registry-global-settings.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/examples/packaging-oci-image/docker-registry-global-settings.xml new file mode 100644 index 000000000000..3fa484eb1868 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/examples/packaging-oci-image/docker-registry-global-settings.xml @@ -0,0 +1,15 @@ + + + + spring-boot-docker-creds + + true + + + my-custom/image-builder:1.0.0 + demo-user + demo-user@example.com + demo-user-password + + + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/pages/build-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/pages/build-image.adoc index 66d108c82947..5d27e4db2b2e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/pages/build-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/antora/modules/maven-plugin/pages/build-image.adoc @@ -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. |=== @@ -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 @@ -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] +---- + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java index 36b45af6ed07..4cad6397816c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/BuildImageMojo.java @@ -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; /** @@ -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 @@ -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); } @@ -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 setter) { + if (StringUtils.hasText(value) && !StringUtils.hasText(currentValue)) { + setter.accept(value); + } + } + private BuildRequest getBuildRequest(Libraries libraries) { ImagePackager imagePackager = new ImagePackager(getArchiveFile(), getBackupFile()); Function content = (owner) -> getApplicationContent(owner, libraries, imagePackager);