Configure Docker host in build plugins

This commit adds the ability to configure the Maven and Gradle
plugins to use a remote Docker daemon using build file
configuration, as an alternative to setting environment variables
to specify remote host connection details.

Fixes gh-23400
This commit is contained in:
Scott Frederick
2020-09-17 14:25:18 -05:00
parent 1c6e37b2ac
commit 54288678d1
18 changed files with 436 additions and 76 deletions

View File

@@ -34,6 +34,24 @@ The following table shows the environment variables and their values:
On Linux and macOS, these environment variables can be set using the command `eval $(minikube docker-env)` after minikube has been started.
Docker daemon connection information can also be provided using `docker` properties in the plugin configuration.
The following table summarizes the available properties:
|===
| Property | Description
| `host`
| URL containing the host and port for the Docker daemon - e.g. `tcp://192.168.99.100:2376`
| `tlsVerify`
| Enable secure HTTPS protocol when set to `true` (optional)
| `certPath`
| Path to certificate and key files for HTTPS (required if `tlsVerify` is `true`, ignored otherwise)
|===
For more details, see also <<build-image-example-docker,examples>>.
[[build-image-docker-registry]]
@@ -220,7 +238,21 @@ The image name can be specified on the command line as well, as shown in this ex
[[build-image-example-docker]]
==== Docker Configuration
If the builder or run image are stored in a private Docker registry that supports user authentication, authentication details can be provided as shown in the following example:
If you need the plugin to communicate with the Docker daemon using a remote connection instead of the default local connection, the connection details can be provided using `docker` properties as shown in the following example:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/packaging/boot-build-image-docker-host.gradle[tags=docker-host]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-build-image-docker-host.gradle.kts[tags=docker-host]
----
If the builder or run image are stored in a private Docker registry that supports user authentication, authentication details can be provided using `docker.registry` properties as shown in the following example:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
@@ -234,7 +266,7 @@ include::../gradle/packaging/boot-build-image-docker-auth-user.gradle[tags=docke
include::../gradle/packaging/boot-build-image-docker-auth-user.gradle.kts[tags=docker-auth-user]
----
If the builder or run image is stored in a private Docker registry that supports token authentication, the token value can be provided as shown in the following example:
If the builder or run image is stored in a private Docker registry that supports token authentication, the token value can be provided using `docker.registry` as shown in the following example:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy

View File

@@ -0,0 +1,18 @@
plugins {
id 'java'
id 'org.springframework.boot' version '{gradle-project-version}'
}
bootJar {
mainClassName 'com.example.ExampleApplication'
}
// tag::docker-host[]
bootBuildImage {
docker {
host = "tcp://192.168.99.100:2376"
tlsVerify = true
certPath = "/home/users/.minikube/certs"
}
}
// end::docker-host[]

View File

@@ -0,0 +1,21 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage
plugins {
java
id("org.springframework.boot") version "{gradle-project-version}"
}
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.ExampleApplication"
}
// tag::docker-host[]
tasks.getByName<BootBuildImage>("bootBuildImage") {
docker {
host = "tcp://192.168.99.100:2376"
tlsVerify = true
certPath = "/home/users/.minikube/certs"
}
}
// end::docker-host[]

View File

@@ -35,6 +35,12 @@ import org.springframework.boot.buildpack.platform.docker.configuration.DockerCo
*/
public class DockerSpec {
private String host;
private boolean tlsVerify;
private String certPath;
private final DockerRegistrySpec registry;
public DockerSpec() {
@@ -45,6 +51,36 @@ public class DockerSpec {
this.registry = registry;
}
@Input
@Optional
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
@Input
@Optional
public Boolean isTlsVerify() {
return this.tlsVerify;
}
public void setTlsVerify(boolean tlsVerify) {
this.tlsVerify = tlsVerify;
}
@Input
@Optional
public String getCertPath() {
return this.certPath;
}
public void setCertPath(String certPath) {
this.certPath = certPath;
}
/**
* Returns the {@link DockerRegistrySpec} that configures registry authentication.
* @return the registry spec
@@ -77,14 +113,28 @@ public class DockerSpec {
* @return the Docker configuration
*/
DockerConfiguration asDockerConfiguration() {
DockerConfiguration dockerConfiguration = new DockerConfiguration();
dockerConfiguration = customizeHost(dockerConfiguration);
dockerConfiguration = customizeAuthentication(dockerConfiguration);
return dockerConfiguration;
}
private DockerConfiguration customizeHost(DockerConfiguration dockerConfiguration) {
if (this.host != null) {
return dockerConfiguration.withHost(this.host, this.tlsVerify, this.certPath);
}
return dockerConfiguration;
}
private DockerConfiguration customizeAuthentication(DockerConfiguration dockerConfiguration) {
if (this.registry == null || this.registry.hasEmptyAuth()) {
return null;
return dockerConfiguration;
}
if (this.registry.hasTokenAuth() && !this.registry.hasUserAuth()) {
return DockerConfiguration.withRegistryTokenAuthentication(this.registry.getToken());
return dockerConfiguration.withRegistryTokenAuthentication(this.registry.getToken());
}
if (this.registry.hasUserAuth() && !this.registry.hasTokenAuth()) {
return DockerConfiguration.withRegistryUserAuthentication(this.registry.getUsername(),
return dockerConfiguration.withRegistryUserAuthentication(this.registry.getUsername(),
this.registry.getPassword(), this.registry.getUrl(), this.registry.getEmail());
}
throw new GradleException(

View File

@@ -20,6 +20,7 @@ import org.gradle.api.GradleException;
import org.junit.jupiter.api.Test;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerConfiguration;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerHost;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerRegistryAuthentication;
import org.springframework.util.Base64Utils;
@@ -35,15 +36,36 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class DockerSpecTests {
@Test
void asDockerConfigurationWithoutRegistry() {
void asDockerConfigurationWithDefaults() {
DockerSpec dockerSpec = new DockerSpec();
assertThat(dockerSpec.asDockerConfiguration()).isNull();
assertThat(dockerSpec.asDockerConfiguration().getHost()).isNull();
assertThat(dockerSpec.asDockerConfiguration().getRegistryAuthentication()).isNull();
}
@Test
void asDockerConfigurationWithEmptyRegistry() {
DockerSpec dockerSpec = new DockerSpec(new DockerSpec.DockerRegistrySpec());
assertThat(dockerSpec.asDockerConfiguration()).isNull();
void asDockerConfigurationWithHostConfiguration() {
DockerSpec dockerSpec = new DockerSpec();
dockerSpec.setHost("docker.example.com");
dockerSpec.setTlsVerify(true);
dockerSpec.setCertPath("/tmp/ca-cert");
DockerConfiguration dockerConfiguration = dockerSpec.asDockerConfiguration();
DockerHost host = dockerConfiguration.getHost();
assertThat(host.getAddress()).isEqualTo("docker.example.com");
assertThat(host.isSecure()).isEqualTo(true);
assertThat(host.getCertificatePath()).isEqualTo("/tmp/ca-cert");
assertThat(dockerSpec.asDockerConfiguration().getRegistryAuthentication()).isNull();
}
@Test
void asDockerConfigurationWithHostConfigurationNoTlsVerify() {
DockerSpec dockerSpec = new DockerSpec();
dockerSpec.setHost("docker.example.com");
DockerConfiguration dockerConfiguration = dockerSpec.asDockerConfiguration();
DockerHost host = dockerConfiguration.getHost();
assertThat(host.getAddress()).isEqualTo("docker.example.com");
assertThat(host.isSecure()).isEqualTo(false);
assertThat(host.getCertificatePath()).isNull();
assertThat(dockerSpec.asDockerConfiguration().getRegistryAuthentication()).isNull();
}
@Test
@@ -61,6 +83,7 @@ public class DockerSpecTests {
.contains("\"username\" : \"user\"").contains("\"password\" : \"secret\"")
.contains("\"email\" : \"docker@example.com\"")
.contains("\"serveraddress\" : \"https://docker.example.com\"");
assertThat(dockerSpec.asDockerConfiguration().getHost()).isNull();
}
@Test