From 57e768a654b41d490137fd81f8db6c1ff0e53c1a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 13 Mar 2026 15:22:59 +0000 Subject: [PATCH] Trim trailing slashes from tcp:// Docker hosts Fixes gh-49055 --- .../configuration/ResolvedDockerHost.java | 12 +++++++-- .../ResolvedDockerHostTests.java | 25 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHost.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHost.java index 59637051bd2..3687d6fc69d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHost.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHost.java @@ -58,9 +58,17 @@ public class ResolvedDockerHost extends DockerHost { public String getAddress() { String address = super.getAddress(); if (address == null) { - address = getDefaultAddress(); + return getDefaultAddress(); } - return address.startsWith(UNIX_SOCKET_PREFIX) ? address.substring(UNIX_SOCKET_PREFIX.length()) : address; + if (address.startsWith(UNIX_SOCKET_PREFIX)) { + return address.substring(UNIX_SOCKET_PREFIX.length()); + } + if (address.startsWith("tcp://")) { + while (address.endsWith("/")) { + address = address.substring(0, address.length() - 1); + } + } + return address; } public boolean isRemote() { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHostTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHostTests.java index ad130b73d17..334692bdd43 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHostTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/ResolvedDockerHostTests.java @@ -140,6 +140,17 @@ class ResolvedDockerHostTests { assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path"); } + @Test + void resolveWhenDockerHostAddressIsTcpWithTrailingReturnsAddress() { + ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get, + new DockerConnectionConfiguration.Host("tcp://192.168.99.100:2376/", true, "/cert-path")); + assertThat(dockerHost.isLocalFileReference()).isFalse(); + assertThat(dockerHost.isRemote()).isTrue(); + assertThat(dockerHost.getAddress()).isEqualTo("tcp://192.168.99.100:2376"); + assertThat(dockerHost.isSecure()).isTrue(); + assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path"); + } + @Test void resolveWhenEnvironmentAddressIsLocalReturnsAddress(@TempDir Path tempDir) throws IOException { String socketFilePath = Files.createTempFile(tempDir, "remote-transport", null).toAbsolutePath().toString(); @@ -180,6 +191,20 @@ class ResolvedDockerHostTests { assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path"); } + @Test + void resolveWhenEnvironmentAddressIsTcpWithTrailingSlashReturnsAddress() { + this.environment.put("DOCKER_HOST", "tcp://192.168.99.100:2376/"); + this.environment.put("DOCKER_TLS_VERIFY", "1"); + this.environment.put("DOCKER_CERT_PATH", "/cert-path"); + ResolvedDockerHost dockerHost = ResolvedDockerHost.from(this.environment::get, + new DockerConnectionConfiguration.Host("tcp://1.1.1.1")); + assertThat(dockerHost.isLocalFileReference()).isFalse(); + assertThat(dockerHost.isRemote()).isTrue(); + assertThat(dockerHost.getAddress()).isEqualTo("tcp://192.168.99.100:2376"); + assertThat(dockerHost.isSecure()).isTrue(); + assertThat(dockerHost.getCertificatePath()).isEqualTo("/cert-path"); + } + @Test void resolveWithDockerHostContextReturnsAddress() throws Exception { this.environment.put("DOCKER_CONFIG", pathToResource("with-default-context/config.json"));