From a65eab6b78414021fef8b08369c72e99ad21ec6f Mon Sep 17 00:00:00 2001 From: Baqirrizvidev <114152937+Baqirrizvidev@users.noreply.github.com> Date: Fri, 17 Jul 2026 11:46:32 +0530 Subject: [PATCH] Do not pull the tiny image for gateway detection when checks are disabled The default gateway detection in DockerClientConfigUtils runs 'ip route' inside a tiny-image container, pulling alpine:3.17 even when checks.disable=true, although the docs state the tiny image is not required when startup checks are disabled. It also let a failed pull (e.g. restricted CI registries) crash docker host IP resolution. Skip container-based gateway detection when checks are disabled and fall back gracefully when the detection container fails. Fixes #11241 Co-Authored-By: Claude Fable 5 --- .../dockerclient/DockerClientConfigUtils.java | 64 +++++++++++-------- .../DockerClientConfigUtilsTest.java | 13 ++++ 2 files changed, 52 insertions(+), 25 deletions(-) diff --git a/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java b/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java index 7206a7e1452..08899ee4f26 100644 --- a/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java +++ b/core/src/main/java/org/testcontainers/dockerclient/DockerClientConfigUtils.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.testcontainers.DockerClientFactory; +import org.testcontainers.utility.TestcontainersConfiguration; import java.io.File; import java.net.URI; @@ -17,32 +18,45 @@ public class DockerClientConfigUtils { public static final boolean IN_A_CONTAINER = new File("/.dockerenv").exists(); @Getter(lazy = true) - private static final Optional defaultGateway = Optional - .ofNullable( - DockerClientFactory - .instance() - .runInsideDocker( - cmd -> cmd.withCmd("sh", "-c", "ip route|awk '/default/ { print $3 }'"), - (client, id) -> { - try { - LogToStringContainerCallback loggingCallback = new LogToStringContainerCallback(); - client - .logContainerCmd(id) - .withStdOut(true) - .withFollowStream(true) - .exec(loggingCallback) - .awaitStarted(); - loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); - return loggingCallback.toString(); - } catch (Exception e) { - log.warn("Can't parse the default gateway IP", e); - return null; - } - } + private static final Optional defaultGateway = resolveDefaultGateway(); + + static Optional resolveDefaultGateway() { + if (TestcontainersConfiguration.getInstance().isDisableChecks()) { + log.debug("Checks are disabled, skipping default gateway detection"); + return Optional.empty(); + } + try { + return Optional + .ofNullable( + DockerClientFactory + .instance() + .runInsideDocker( + cmd -> cmd.withCmd("sh", "-c", "ip route|awk '/default/ { print $3 }'"), + (client, id) -> { + try { + LogToStringContainerCallback loggingCallback = new LogToStringContainerCallback(); + client + .logContainerCmd(id) + .withStdOut(true) + .withFollowStream(true) + .exec(loggingCallback) + .awaitStarted(); + loggingCallback.awaitCompletion(3, TimeUnit.SECONDS); + return loggingCallback.toString(); + } catch (Exception e) { + log.warn("Can't parse the default gateway IP", e); + return null; + } + } + ) ) - ) - .map(StringUtils::trimToEmpty) - .filter(StringUtils::isNotBlank); + .map(StringUtils::trimToEmpty) + .filter(StringUtils::isNotBlank); + } catch (Exception e) { + log.warn("Can't detect the default gateway", e); + return Optional.empty(); + } + } /** * @deprecated use {@link DockerClientProviderStrategy#getDockerHostIpAddress()} diff --git a/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java b/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java index f3bc15d2c22..4a649cee1bd 100644 --- a/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java +++ b/core/src/test/java/org/testcontainers/dockerclient/DockerClientConfigUtilsTest.java @@ -4,12 +4,17 @@ import org.assertj.core.api.Assumptions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; import org.testcontainers.DockerClientFactory; +import org.testcontainers.utility.MockTestcontainersConfigurationExtension; +import org.testcontainers.utility.TestcontainersConfiguration; import java.net.URI; import static org.assertj.core.api.Assertions.assertThat; +@ExtendWith(MockTestcontainersConfigurationExtension.class) class DockerClientConfigUtilsTest { DockerClient client = DockerClientFactory.lazyClient(); @@ -61,4 +66,12 @@ void getDockerHostIpAddressShouldReturnNullWhenUnsupportedUriScheme() { void getDefaultGateway() { assertThat(DockerClientConfigUtils.getDefaultGateway()).isNotNull(); } + + @Test + @Timeout(5) + void resolveDefaultGatewayShouldNotRunContainerWhenChecksAreDisabled() { + Mockito.doReturn(true).when(TestcontainersConfiguration.getInstance()).isDisableChecks(); + + assertThat(DockerClientConfigUtils.resolveDefaultGateway()).isEmpty(); + } }