Add bindings option for image building
This commit adds configuration to the Maven and Gradle plugins to allow a list of volume mount bindings to be provided to the image building goal and task. This enables service bindings to be mounted in the builder image that are recognized by buildpacks to support custom certificates, build tool configuration, APM integration, and other buildpack features. Fixes gh-23518
This commit is contained in:
@@ -157,13 +157,29 @@ a|Buildpacks that the builder should use when building the image.
|
||||
Only the specified buildpacks will be used, overriding the default buildpacks included in the builder.
|
||||
Buildpack references must be in one of the following forms:
|
||||
|
||||
* Buildpack in the builder - [urn:cnb:builder:]<buildpack id>[@<version>]
|
||||
* Buildpack in a directory on the file system - [file://]<path>
|
||||
* Buildpack in a gzipped tar (.tgz) file on the file system - [file://]<path>/<file name>
|
||||
* Buildpack in an OCI image - [docker://]<host>/<repo>[:<tag>][@<digest>]
|
||||
* Buildpack in the builder - `[urn:cnb:builder:]<buildpack ID>[@<version>]`
|
||||
* Buildpack in a directory on the file system - `[file://]<path>`
|
||||
* Buildpack in a gzipped tar (.tgz) file on the file system - `[file://]<path>/<file name>`
|
||||
* Buildpack in an OCI image - `[docker://]<host>/<repo>[:<tag>][@<digest>]`
|
||||
|
|
||||
| None, indicating the builder should use the buildpacks included in it.
|
||||
|
||||
| `bindings`
|
||||
a|https://docs.docker.com/storage/bind-mounts/[Volume bind mounts] that should be mounted to the builder container when building the image.
|
||||
The bindings will be passed unparsed and unvalidated to Docker when creating the builder container.
|
||||
Bindings must be in one of the following forms:
|
||||
|
||||
* `<host source path>:<container destination path>[:<options>]`
|
||||
* `<host volume name>:<container destination path>[:<options>]`
|
||||
|
||||
Where `<options>` can contain:
|
||||
|
||||
* `ro` to mount the volume as read-only in the container
|
||||
* `rw` to mount the volume as readable and writable in the container
|
||||
* `volume-opt=key=value` to specify key-value pairs consisting of an option name and its value
|
||||
|
|
||||
|
|
||||
|
||||
| `cleanCache`
|
||||
| Whether to clean the cache before building.
|
||||
| `spring-boot.build-image.cleanCache`
|
||||
|
||||
@@ -168,6 +168,15 @@ public class BuildImageTests extends AbstractArchiveIntegrationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWithBindingContainingInvalidCertificate(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("build-image-bindings").goals("package")
|
||||
.systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT")
|
||||
.executeAndFail((project) -> assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("failed to decode certificate")
|
||||
.contains("/platform/bindings/ca-certificates/test.crt"));
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void failsWhenPublishWithoutPublishRegistryConfigured(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("build-image").goals("package").systemProperty("spring-boot.build-image.publish", "true")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
not a valid certificate
|
||||
@@ -0,0 +1 @@
|
||||
ca-certificates
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>build-image-bindings</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-image</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<image>
|
||||
<bindings>
|
||||
<binding>${basedir}/bindings/ca-certificates:/platform/bindings/ca-certificates</binding>
|
||||
</bindings>
|
||||
</image>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Launched");
|
||||
synchronized(args) {
|
||||
args.wait(); // Prevent exit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import org.apache.maven.artifact.Artifact;
|
||||
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
||||
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.ImageName;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.ImageReference;
|
||||
import org.springframework.boot.buildpack.platform.io.Owner;
|
||||
@@ -59,6 +60,8 @@ public class Image {
|
||||
|
||||
List<String> buildpacks;
|
||||
|
||||
List<String> bindings;
|
||||
|
||||
/**
|
||||
* The name of the created image.
|
||||
* @return the image name
|
||||
@@ -183,6 +186,9 @@ public class Image {
|
||||
request = request
|
||||
.withBuildpacks(this.buildpacks.stream().map(BuildpackReference::of).collect(Collectors.toList()));
|
||||
}
|
||||
if (this.bindings != null && !this.bindings.isEmpty()) {
|
||||
request = request.withBindings(this.bindings.stream().map(Binding::of).collect(Collectors.toList()));
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.buildpack.platform.build.BuildRequest;
|
||||
import org.springframework.boot.buildpack.platform.build.BuildpackReference;
|
||||
import org.springframework.boot.buildpack.platform.build.PullPolicy;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
||||
import org.springframework.boot.buildpack.platform.io.Owner;
|
||||
import org.springframework.boot.buildpack.platform.io.TarArchive;
|
||||
|
||||
@@ -68,6 +69,7 @@ class ImageTests {
|
||||
assertThat(request.isVerboseLogging()).isFalse();
|
||||
assertThat(request.getPullPolicy()).isEqualTo(PullPolicy.ALWAYS);
|
||||
assertThat(request.getBuildpacks()).isEmpty();
|
||||
assertThat(request.getBindings()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -135,6 +137,15 @@ class ImageTests {
|
||||
BuildpackReference.of("example/buildpack2@0.0.2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBuildRequestWhenHasBindingsUsesBindings() {
|
||||
Image image = new Image();
|
||||
image.bindings = Arrays.asList("host-src:container-dest:ro", "volume-name:container-dest:rw");
|
||||
BuildRequest request = image.getBuildRequest(createArtifact(), mockApplicationContent());
|
||||
assertThat(request.getBindings()).containsExactly(Binding.of("host-src:container-dest:ro"),
|
||||
Binding.of("volume-name:container-dest:rw"));
|
||||
}
|
||||
|
||||
private Artifact createArtifact() {
|
||||
return new DefaultArtifact("com.example", "my-app", VersionRange.createFromVersion("0.0.1-SNAPSHOT"), "compile",
|
||||
"jar", null, new DefaultArtifactHandler());
|
||||
|
||||
Reference in New Issue
Block a user