diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java index 1473c4f353..bf5fc8fd4d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/DockerApi.java @@ -187,7 +187,7 @@ public class DockerApi { listener.onUpdate(event); }); } - return inspect(reference.withDigest(digestCapture.getCapturedDigest())); + return inspect(reference); } finally { listener.onFinish(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchive.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchive.java index 01e2225604..00383b5a4c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchive.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchive.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 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. @@ -61,6 +61,8 @@ public class ImageArchive implements TarArchive { private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_ZONED_DATE_TIME .withZone(ZoneOffset.UTC); + private static final String EMPTY_LAYER_NAME_PREFIX = "blank_"; + private static final IOConsumer NO_UPDATES = (update) -> { }; @@ -125,6 +127,9 @@ public class ImageArchive implements TarArchive { } private List writeLayers(Layout writer) throws IOException { + for (int i = 0; i < this.existingLayers.size(); i++) { + writeEmptyLayer(writer, EMPTY_LAYER_NAME_PREFIX + i); + } List writtenLayers = new ArrayList<>(); for (Layer layer : this.newLayers) { writtenLayers.add(writeLayer(writer, layer)); @@ -132,9 +137,13 @@ public class ImageArchive implements TarArchive { return Collections.unmodifiableList(writtenLayers); } + private void writeEmptyLayer(Layout writer, String name) throws IOException { + writer.file(name, Owner.ROOT, Content.of("")); + } + private LayerId writeLayer(Layout writer, Layer layer) throws IOException { LayerId id = layer.getId(); - writer.file("/" + id.getHash() + ".tar", Owner.ROOT, layer); + writer.file(id.getHash() + ".tar", Owner.ROOT, layer); return id; } @@ -144,7 +153,7 @@ public class ImageArchive implements TarArchive { String json = this.objectMapper.writeValueAsString(config).replace("\r\n", "\n"); MessageDigest digest = MessageDigest.getInstance("SHA-256"); InspectedContent content = InspectedContent.of(Content.of(json), digest::update); - String name = "/" + LayerId.ofSha256Digest(digest.digest()).getHash() + ".json"; + String name = LayerId.ofSha256Digest(digest.digest()).getHash() + ".json"; writer.file(name, Owner.ROOT, content); return name; } @@ -187,7 +196,7 @@ public class ImageArchive implements TarArchive { private void writeManifest(Layout writer, String config, List writtenLayers) throws IOException { ArrayNode manifest = createManifest(config, writtenLayers); String manifestJson = this.objectMapper.writeValueAsString(manifest); - writer.file("/manifest.json", Owner.ROOT, Content.of(manifestJson)); + writer.file("manifest.json", Owner.ROOT, Content.of(manifestJson)); } private ArrayNode createManifest(String config, List writtenLayers) { @@ -204,7 +213,7 @@ public class ImageArchive implements TarArchive { private ArrayNode getManifestLayers(List writtenLayers) { ArrayNode layers = this.objectMapper.createArrayNode(); for (int i = 0; i < this.existingLayers.size(); i++) { - layers.add(""); + layers.add(EMPTY_LAYER_NAME_PREFIX + i); } writtenLayers.stream().map((id) -> id.getHash() + ".tar").forEach(layers::add); return layers; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilderTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilderTests.java index 9ba9ab9e82..53909aa0ff 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilderTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/EphemeralBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -58,6 +58,8 @@ import static org.assertj.core.api.Assertions.entry; */ class EphemeralBuilderTests extends AbstractJsonTests { + private static final int EXISTING_IMAGE_LAYER_COUNT = 43; + @TempDir File temp; @@ -131,7 +133,7 @@ class EphemeralBuilderTests extends AbstractJsonTests { void getArchiveContainsEnvLayer() throws Exception { EphemeralBuilder builder = new EphemeralBuilder(this.owner, this.image, this.targetImage, this.metadata, this.creator, this.env, this.buildpacks); - File directory = unpack(getLayer(builder.getArchive(), 0), "env"); + File directory = unpack(getLayer(builder.getArchive(), EXISTING_IMAGE_LAYER_COUNT), "env"); assertThat(new File(directory, "platform/env/spring")).usingCharset(StandardCharsets.UTF_8).hasContent("boot"); assertThat(new File(directory, "platform/env/empty")).usingCharset(StandardCharsets.UTF_8).hasContent(""); } @@ -154,10 +156,13 @@ class EphemeralBuilderTests extends AbstractJsonTests { this.buildpacks = Buildpacks.of(buildpackList); EphemeralBuilder builder = new EphemeralBuilder(this.owner, this.image, this.targetImage, this.metadata, this.creator, null, this.buildpacks); - assertBuildpackLayerContent(builder, 0, "/cnb/buildpacks/example_buildpack1/0.0.1/buildpack.toml"); - assertBuildpackLayerContent(builder, 1, "/cnb/buildpacks/example_buildpack2/0.0.2/buildpack.toml"); - assertBuildpackLayerContent(builder, 2, "/cnb/buildpacks/example_buildpack3/0.0.3/buildpack.toml"); - File orderDirectory = unpack(getLayer(builder.getArchive(), 3), "order"); + assertBuildpackLayerContent(builder, EXISTING_IMAGE_LAYER_COUNT, + "/cnb/buildpacks/example_buildpack1/0.0.1/buildpack.toml"); + assertBuildpackLayerContent(builder, EXISTING_IMAGE_LAYER_COUNT + 1, + "/cnb/buildpacks/example_buildpack2/0.0.2/buildpack.toml"); + assertBuildpackLayerContent(builder, EXISTING_IMAGE_LAYER_COUNT + 2, + "/cnb/buildpacks/example_buildpack3/0.0.3/buildpack.toml"); + File orderDirectory = unpack(getLayer(builder.getArchive(), EXISTING_IMAGE_LAYER_COUNT + 3), "order"); assertThat(new File(orderDirectory, "cnb/order.toml")).usingCharset(StandardCharsets.UTF_8) .hasContent(content("order.toml")); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java index d1272ff2a3..e6a76b6f41 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/DockerApiTests.java @@ -164,8 +164,7 @@ class DockerApiTests { void pullPullsImageAndProducesEvents() throws Exception { ImageReference reference = ImageReference.of("gcr.io/paketo-buildpacks/builder:base"); URI createUri = new URI(IMAGES_URL + "/create?fromImage=gcr.io%2Fpaketo-buildpacks%2Fbuilder%3Abase"); - String imageHash = "4acb6bfd6c4f0cabaf7f3690e444afe51f1c7de54d51da7e63fac709c56f1c30"; - URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder@sha256:" + imageHash + "/json"); + URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder:base/json"); given(http().post(eq(createUri), isNull())).willReturn(responseOf("pull-stream.json")); given(http().get(imageUri)).willReturn(responseOf("type/image.json")); Image image = this.api.pull(reference, this.pullListener); @@ -180,8 +179,7 @@ class DockerApiTests { void pullWithRegistryAuthPullsImageAndProducesEvents() throws Exception { ImageReference reference = ImageReference.of("gcr.io/paketo-buildpacks/builder:base"); URI createUri = new URI(IMAGES_URL + "/create?fromImage=gcr.io%2Fpaketo-buildpacks%2Fbuilder%3Abase"); - String imageHash = "4acb6bfd6c4f0cabaf7f3690e444afe51f1c7de54d51da7e63fac709c56f1c30"; - URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder@sha256:" + imageHash + "/json"); + URI imageUri = new URI(IMAGES_URL + "/gcr.io/paketo-buildpacks/builder:base/json"); given(http().post(eq(createUri), eq("auth token"))).willReturn(responseOf("pull-stream.json")); given(http().get(imageUri)).willReturn(responseOf("type/image.json")); Image image = this.api.pull(reference, this.pullListener, "auth token"); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java index 8457a45979..318bf7985c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/type/ImageArchiveTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 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. @@ -40,6 +40,8 @@ import static org.assertj.core.api.Assertions.assertThat; */ class ImageArchiveTests extends AbstractJsonTests { + private static final int EXISTING_IMAGE_LAYER_COUNT = 46; + @Test void fromImageWritesToValidArchiveTar() throws Exception { Image image = Image.of(getContent("image.json")); @@ -51,13 +53,16 @@ class ImageArchiveTests extends AbstractJsonTests { archive.writeTo(outputStream); try (TarArchiveInputStream tar = new TarArchiveInputStream( new ByteArrayInputStream(outputStream.toByteArray()))) { + for (int i = 0; i < EXISTING_IMAGE_LAYER_COUNT; i++) { + TarArchiveEntry blankEntry = tar.getNextTarEntry(); + assertThat(blankEntry.getName()).isEqualTo("blank_" + i); + } TarArchiveEntry layerEntry = tar.getNextTarEntry(); byte[] layerContent = read(tar, layerEntry.getSize()); TarArchiveEntry configEntry = tar.getNextTarEntry(); byte[] configContent = read(tar, configEntry.getSize()); TarArchiveEntry manifestEntry = tar.getNextTarEntry(); byte[] manifestContent = read(tar, manifestEntry.getSize()); - assertThat(tar.getNextTarEntry()).isNull(); assertExpectedLayer(layerEntry, layerContent); assertExpectedConfig(configEntry, configContent); assertExpectedManifest(manifestEntry, manifestContent); @@ -65,7 +70,7 @@ class ImageArchiveTests extends AbstractJsonTests { } private void assertExpectedLayer(TarArchiveEntry entry, byte[] content) throws Exception { - assertThat(entry.getName()).isEqualTo("/bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar"); + assertThat(entry.getName()).isEqualTo("bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar"); try (TarArchiveInputStream tar = new TarArchiveInputStream(new ByteArrayInputStream(content))) { TarArchiveEntry contentEntry = tar.getNextTarEntry(); assertThat(contentEntry.getName()).isEqualTo("/spring/"); @@ -73,14 +78,14 @@ class ImageArchiveTests extends AbstractJsonTests { } private void assertExpectedConfig(TarArchiveEntry entry, byte[] content) throws Exception { - assertThat(entry.getName()).isEqualTo("/682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json"); + assertThat(entry.getName()).isEqualTo("682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json"); String actualJson = new String(content, StandardCharsets.UTF_8); String expectedJson = StreamUtils.copyToString(getContent("image-archive-config.json"), StandardCharsets.UTF_8); JSONAssert.assertEquals(expectedJson, actualJson, false); } private void assertExpectedManifest(TarArchiveEntry entry, byte[] content) throws Exception { - assertThat(entry.getName()).isEqualTo("/manifest.json"); + assertThat(entry.getName()).isEqualTo("manifest.json"); String actualJson = new String(content, StandardCharsets.UTF_8); String expectedJson = StreamUtils.copyToString(getContent("image-archive-manifest.json"), StandardCharsets.UTF_8); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/image-archive-manifest.json b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/image-archive-manifest.json index 0e3a641407..4830d4e8e1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/image-archive-manifest.json +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/resources/org/springframework/boot/buildpack/platform/docker/type/image-archive-manifest.json @@ -1,53 +1,53 @@ [ { - "Config": "/682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json", + "Config": "682f8d24b9d9c313d1190a0e955dcb5e65ec9beea40420999839c6f0cbb38382.json", "Layers": [ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", + "blank_0", + "blank_1", + "blank_2", + "blank_3", + "blank_4", + "blank_5", + "blank_6", + "blank_7", + "blank_8", + "blank_9", + "blank_10", + "blank_11", + "blank_12", + "blank_13", + "blank_14", + "blank_15", + "blank_16", + "blank_17", + "blank_18", + "blank_19", + "blank_20", + "blank_21", + "blank_22", + "blank_23", + "blank_24", + "blank_25", + "blank_26", + "blank_27", + "blank_28", + "blank_29", + "blank_30", + "blank_31", + "blank_32", + "blank_33", + "blank_34", + "blank_35", + "blank_36", + "blank_37", + "blank_38", + "blank_39", + "blank_40", + "blank_41", + "blank_42", + "blank_43", + "blank_44", + "blank_45", "bb09e17fd1bd2ee47155f1349645fcd9fff31e1247c7ed99cad469f1c16a4216.tar" ], "RepoTags": [ diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 3b16800e81..af20fafc12 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -16,7 +16,7 @@ The `bootBuildImage` task requires access to a Docker daemon. By default, it will communicate with a Docker daemon over a local connection. This works with https://docs.docker.com/install/[Docker Engine] on all supported platforms without configuration. -Environment variables can be set to configure the `bootBuildImage` task to use the https://minikube.sigs.k8s.io/docs/tasks/docker_daemon/[Docker daemon provided by minikube]. +Environment variables can be set to configure the `bootBuildImage` task to use an alternative local or remote connection. The following table shows the environment variables and their values: |=== @@ -32,8 +32,6 @@ The following table shows the environment variables and their values: | Path to certificate and key files for HTTPS (required if `DOCKER_TLS_VERIFY=1`, ignored otherwise) |=== -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: @@ -416,7 +414,14 @@ include::../gradle/packaging/boot-build-image-caches.gradle.kts[tags=caches] [[build-image.examples.docker]] === Docker Configuration -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: +[[build-image.examples.docker.minikube]] +==== Docker Configuration for minikube + +The plugin can communicate with the https://minikube.sigs.k8s.io/docs/tasks/docker_daemon/[Docker daemon provided by minikube] instead of the default local connection. + +On Linux and macOS, environment variables can be set using the command `eval $(minikube docker-env)` after minikube has been started. + +The plugin can also be configured to use the minikube daemon by providing connection details similar to those shown in the following example: [source,groovy,indent=0,subs="verbatim,attributes",role="primary"] .Groovy @@ -430,6 +435,28 @@ include::../gradle/packaging/boot-build-image-docker-host.gradle[tags=docker-hos include::../gradle/packaging/boot-build-image-docker-host.gradle.kts[tags=docker-host] ---- +[[build-image.examples.docker.podman]] +==== Docker Configuration for podman + +The plugin can communicate with a https://podman.io/[podman container engine]. + +The plugin can be configured to use podman local connection by providing connection details similar to those shown in the following example: + +[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] +.Groovy +---- +include::../gradle/packaging/boot-build-image-docker-host-podman.gradle[tags=docker-host] +---- + +[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] +.Kotlin +---- +include::../gradle/packaging/boot-build-image-docker-host-podman.gradle.kts[tags=docker-host] +---- + +[[build-image.examples.docker.auth]] +==== Docker Configuration for Authentication + If the builder or run image are stored in a private Docker registry that supports user authentication, authentication details can be provided using `docker.builderRegistry` properties as shown in the following example: [source,groovy,indent=0,subs="verbatim,attributes",role="primary"] diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host-podman.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host-podman.gradle new file mode 100644 index 0000000000..c9e7e5c582 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host-podman.gradle @@ -0,0 +1,24 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '{gradle-project-version}' +} + +tasks.named("bootJar") { + mainClass = 'com.example.ExampleApplication' +} + +// tag::docker-host[] +tasks.named("bootBuildImage") { + docker { + host = "unix:///run/user/1000/podman/podman.sock" + bindHostToBuilder = true + } +} +// end::docker-host[] + +tasks.register("bootBuildImageDocker") { + doFirst { + println("host=${tasks.bootBuildImage.docker.host}") + println("bindHostToBuilder=${tasks.bootBuildImage.docker.bindHostToBuilder}") + } +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host-podman.gradle.kts b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host-podman.gradle.kts new file mode 100644 index 0000000000..94e4cd0993 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host-podman.gradle.kts @@ -0,0 +1,27 @@ +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.named("bootJar") { + mainClass.set("com.example.ExampleApplication") +} + +// tag::docker-host[] +tasks.named("bootBuildImage") { + docker { + host = "unix:///run/user/1000/podman/podman.sock" + isBindHostToBuilder = true + } +} +// end::docker-host[] + +tasks.register("bootBuildImageDocker") { + doFirst { + println("host=${tasks.getByName("bootBuildImage").docker.host}") + println("bindHostToBuilder=${tasks.getByName("bootBuildImage").docker.isBindHostToBuilder}") + } +} diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle index 8ee8a2d67d..8f41766fa8 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle @@ -12,7 +12,7 @@ tasks.named("bootBuildImage") { docker { host = "tcp://192.168.99.100:2376" tlsVerify = true - certPath = "/home/users/.minikube/certs" + certPath = "/home/user/.minikube/certs" } } // end::docker-host[] diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle.kts b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle.kts index 3b72699745..61c1a8f61c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle.kts +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/docs/gradle/packaging/boot-build-image-docker-host.gradle.kts @@ -15,7 +15,7 @@ tasks.named("bootBuildImage") { docker { host = "tcp://192.168.99.100:2376" isTlsVerify = true - certPath = "/home/users/.minikube/certs" + certPath = "/home/user/.minikube/certs" } } // end::docker-host[] diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java index 06ace0485c..9a7e64872f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/docs/PackagingDocumentationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -279,11 +279,19 @@ class PackagingDocumentationTests { } @TestTemplate - void bootBuildImageWithDockerHost() { + void bootBuildImageWithDockerHostMinikube() { BuildResult result = this.gradleBuild.script("src/docs/gradle/packaging/boot-build-image-docker-host") .build("bootBuildImageDocker"); assertThat(result.getOutput()).contains("host=tcp://192.168.99.100:2376").contains("tlsVerify=true") - .contains("certPath=/home/users/.minikube/certs"); + .contains("certPath=/home/user/.minikube/certs"); + } + + @TestTemplate + void bootBuildImageWithDockerHostPodman() { + BuildResult result = this.gradleBuild.script("src/docs/gradle/packaging/boot-build-image-docker-host-podman") + .build("bootBuildImageDocker"); + assertThat(result.getOutput()).contains("host=unix:///run/user/1000/podman/podman.sock") + .contains("bindHostToBuilder=true"); } @TestTemplate diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc index 17157e792d..1fbcabd2ef 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/asciidoc/packaging-oci-image.adoc @@ -25,7 +25,7 @@ The `build-image` goal requires access to a Docker daemon. By default, it will communicate with a Docker daemon over a local connection. This works with https://docs.docker.com/install/[Docker Engine] on all supported platforms without configuration. -Environment variables can be set to configure the `build-image` goal to use the https://minikube.sigs.k8s.io/docs/tasks/docker_daemon/[Docker daemon provided by minikube]. +Environment variables can be set to configure the `build-image` goal to use an alternative local or remote connection. The following table shows the environment variables and their values: |=== @@ -41,8 +41,6 @@ The following table shows the environment variables and their values: | Path to certificate and key files for HTTPS (required if `DOCKER_TLS_VERIFY=1`, ignored otherwise) |=== -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` parameters in the plugin configuration. The following table summarizes the available parameters: @@ -372,13 +370,35 @@ include::../maven/packaging-oci-image/caches-pom.xml[tags=caches] [[build-image.examples.docker]] === Docker Configuration -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` parameters as shown in the following example: +[[build-image.examples.docker.minikube]] +==== Docker Configuration for minikube + +The plugin can communicate with the https://minikube.sigs.k8s.io/docs/tasks/docker_daemon/[Docker daemon provided by minikube] instead of the default local connection. + +On Linux and macOS, environment variables can be set using the command `eval $(minikube docker-env)` after minikube has been started. + +The plugin can also be configured to use the minikube daemon by providing connection details similar to those shown in the following example: + +[source,xml,indent=0,subs="verbatim,attributes",tabsize=4] +---- +include::../maven/packaging-oci-image/docker-minikube-pom.xml[tags=docker-minikube] +---- + +[[build-image.examples.docker.podman]] +==== Docker Configuration for podman + +The plugin can communicate with a https://podman.io/[podman container engine]. + +The plugin can be configured to use podman local connection by providing connection details similar to those shown in the following example: [source,xml,indent=0,subs="verbatim,attributes",tabsize=4] ---- -include::../maven/packaging-oci-image/docker-remote-pom.xml[tags=docker-remote] +include::../maven/packaging-oci-image/docker-podman-pom.xml[tags=docker-podman] ---- +[[build-image.examples.docker.auth]] +==== Docker Configuration for Authentication + If the builder or run image are stored in a private Docker registry that supports user authentication, authentication details can be provided using `docker.builderRegistry` parameters as shown in the following example: [source,xml,indent=0,subs="verbatim,attributes",tabsize=4] diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-remote-pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-minikube-pom.xml similarity index 87% rename from spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-remote-pom.xml rename to spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-minikube-pom.xml index 942e3cdebd..94151f175c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-remote-pom.xml +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-minikube-pom.xml @@ -1,5 +1,5 @@ - + @@ -17,5 +17,5 @@ - + diff --git a/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-podman-pom.xml b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-podman-pom.xml new file mode 100644 index 0000000000..778e6ef017 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/docs/maven/packaging-oci-image/docker-podman-pom.xml @@ -0,0 +1,20 @@ + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + unix:///run/user/1000/podman/podman.sock + true + + + + + + + +