From b98c3735b597c734382601416eaaa48bd12fabca Mon Sep 17 00:00:00 2001 From: kdelay Date: Fri, 24 Jul 2026 09:13:55 +0900 Subject: [PATCH 1/4] Avoid duplicate /dev/shm bind when reusing BrowserWebDriverContainer configure() runs on every start(), and on non-Windows hosts it unconditionally appended a /dev/shm bind to the container binds. When a BrowserWebDriverContainer is stopped and started again (reuse), the bind was added a second time, so container creation failed with "Status 400: Duplicate mount point: /dev/shm". Only add the /dev/shm bind if one is not already present, in both the selenium module container and its deprecated counterpart. Fixes #11941 Signed-off-by: kdelay --- .../containers/BrowserWebDriverContainer.java | 2 +- .../selenium/BrowserWebDriverContainer.java | 2 +- .../BrowserWebDriverContainerReuseTest.java | 31 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java diff --git a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java index 53ee8ba5577..52b8d0b0b5e 100644 --- a/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java +++ b/modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java @@ -220,7 +220,7 @@ protected void configure() { if (getShmSize() == null) { if (SystemUtils.IS_OS_WINDOWS) { withSharedMemorySize(512 * FileUtils.ONE_MB); - } else { + } else if (getBinds().stream().noneMatch(bind -> "/dev/shm".equals(bind.getVolume().getPath()))) { this.getBinds().add(new Bind("/dev/shm", new Volume("/dev/shm"), AccessMode.rw)); } } diff --git a/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java b/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java index 97ac23f5d55..fce30cc5fc5 100644 --- a/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java +++ b/modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java @@ -164,7 +164,7 @@ protected void configure() { if (getShmSize() == null) { if (SystemUtils.IS_OS_WINDOWS) { withSharedMemorySize(512 * FileUtils.ONE_MB); - } else { + } else if (getBinds().stream().noneMatch(bind -> "/dev/shm".equals(bind.getVolume().getPath()))) { this.getBinds().add(new Bind("/dev/shm", new Volume("/dev/shm"), AccessMode.rw)); } } diff --git a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java new file mode 100644 index 00000000000..ace8d924e5c --- /dev/null +++ b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java @@ -0,0 +1,31 @@ +package org.testcontainers.selenium; + +import com.github.dockerjava.api.model.Bind; +import org.junit.jupiter.api.Test; +import org.testcontainers.utility.DockerImageName; + +import static org.assertj.core.api.Assertions.assertThat; + +class BrowserWebDriverContainerReuseTest { + + private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.10.0"); + + @Test + void configureDoesNotAddDuplicateShmBindOnReuse() { + BrowserWebDriverContainer container = new BrowserWebDriverContainer(CHROME_IMAGE); + + // configure() runs on every start(), so a reused container that is started + // more than once must not accumulate duplicate /dev/shm binds (see #11941). + container.configure(); + container.configure(); + + long shmBinds = container + .getBinds() + .stream() + .map(Bind::getVolume) + .filter(volume -> "/dev/shm".equals(volume.getPath())) + .count(); + + assertThat(shmBinds).isEqualTo(1); + } +} From f66bd9e19674aa9c597e94324ce59d59b143c39a Mon Sep 17 00:00:00 2001 From: kdelay Date: Fri, 24 Jul 2026 22:11:43 +0900 Subject: [PATCH 2/4] Disable duplicate /dev/shm bind reuse test on Windows The Windows branch of configure() does not add the /dev/shm bind, so the test asserting exactly one /dev/shm bind after two configure() calls would fail on Windows. Guard it with @DisabledOnOs(OS.WINDOWS). --- .../selenium/BrowserWebDriverContainerReuseTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java index ace8d924e5c..62c9a3c4b6c 100644 --- a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java @@ -2,6 +2,8 @@ import com.github.dockerjava.api.model.Bind; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.testcontainers.utility.DockerImageName; import static org.assertj.core.api.Assertions.assertThat; @@ -11,6 +13,7 @@ class BrowserWebDriverContainerReuseTest { private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.10.0"); @Test + @DisabledOnOs(OS.WINDOWS) void configureDoesNotAddDuplicateShmBindOnReuse() { BrowserWebDriverContainer container = new BrowserWebDriverContainer(CHROME_IMAGE); From ab77082676765b85d6cc755541a090df96f25ec9 Mon Sep 17 00:00:00 2001 From: kdelay Date: Sun, 26 Jul 2026 19:28:30 +0900 Subject: [PATCH 3/4] Cover the deprecated BrowserWebDriverContainer in the reuse test The /dev/shm guard was applied both to the selenium module container and to its deprecated org.testcontainers.containers counterpart, but only the former was covered: reverting the deprecated hunk on its own left BrowserWebDriverContainerReuseTest green, and SeleniumStartTest starts each container once so it does not exercise reuse either. Mirror the regression test into org.testcontainers.containers so both hunks are guarded, and align the image tag with the 4.13.0 that the other selenium tests use. Signed-off-by: kdelay Co-authored-by: renechoi --- .../BrowserWebDriverContainerReuseTest.java | 34 +++++++++++++++++++ .../BrowserWebDriverContainerReuseTest.java | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java diff --git a/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java new file mode 100644 index 00000000000..bce998cf53b --- /dev/null +++ b/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java @@ -0,0 +1,34 @@ +package org.testcontainers.containers; + +import com.github.dockerjava.api.model.Bind; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; +import org.testcontainers.utility.DockerImageName; + +import static org.assertj.core.api.Assertions.assertThat; + +class BrowserWebDriverContainerReuseTest { + + private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.13.0"); + + @Test + @DisabledOnOs(OS.WINDOWS) + void configureDoesNotAddDuplicateShmBindOnReuse() { + BrowserWebDriverContainer container = new BrowserWebDriverContainer<>(CHROME_IMAGE); + + // configure() runs on every start(), so a reused container that is started + // more than once must not accumulate duplicate /dev/shm binds (see #11941). + container.configure(); + container.configure(); + + long shmBinds = container + .getBinds() + .stream() + .map(Bind::getVolume) + .filter(volume -> "/dev/shm".equals(volume.getPath())) + .count(); + + assertThat(shmBinds).isEqualTo(1); + } +} diff --git a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java index 62c9a3c4b6c..dcbcd7409e1 100644 --- a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java @@ -10,7 +10,7 @@ class BrowserWebDriverContainerReuseTest { - private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.10.0"); + private static final DockerImageName CHROME_IMAGE = DockerImageName.parse("selenium/standalone-chrome:4.13.0"); @Test @DisabledOnOs(OS.WINDOWS) From e4fce60fb6074ff23b1cf602d3b9e1ed2511d8c5 Mon Sep 17 00:00:00 2001 From: kdelay Date: Sat, 1 Aug 2026 10:44:52 +0900 Subject: [PATCH 4/4] Cover a caller-supplied /dev/shm bind in the reuse test --- .../BrowserWebDriverContainerReuseTest.java | 14 ++++++++++++++ .../BrowserWebDriverContainerReuseTest.java | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java index bce998cf53b..f8665a75eb6 100644 --- a/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java @@ -31,4 +31,18 @@ void configureDoesNotAddDuplicateShmBindOnReuse() { assertThat(shmBinds).isEqualTo(1); } + + @Test + @DisabledOnOs(OS.WINDOWS) + void configureKeepsACallerSuppliedShmBind() { + BrowserWebDriverContainer container = new BrowserWebDriverContainer<>(CHROME_IMAGE); + container.withFileSystemBind("/tmp/shm", "/dev/shm", BindMode.READ_ONLY); + + container.configure(); + + assertThat(container.getBinds()) + .filteredOn(bind -> "/dev/shm".equals(bind.getVolume().getPath())) + .singleElement() + .satisfies(bind -> assertThat(bind.getPath()).isEqualTo("/tmp/shm")); + } } diff --git a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java index dcbcd7409e1..8ee4e3930c2 100644 --- a/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java +++ b/modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; import org.junit.jupiter.api.condition.OS; +import org.testcontainers.containers.BindMode; import org.testcontainers.utility.DockerImageName; import static org.assertj.core.api.Assertions.assertThat; @@ -31,4 +32,18 @@ void configureDoesNotAddDuplicateShmBindOnReuse() { assertThat(shmBinds).isEqualTo(1); } + + @Test + @DisabledOnOs(OS.WINDOWS) + void configureKeepsACallerSuppliedShmBind() { + BrowserWebDriverContainer container = new BrowserWebDriverContainer(CHROME_IMAGE); + container.withFileSystemBind("/tmp/shm", "/dev/shm", BindMode.READ_ONLY); + + container.configure(); + + assertThat(container.getBinds()) + .filteredOn(bind -> "/dev/shm".equals(bind.getVolume().getPath())) + .singleElement() + .satisfies(bind -> assertThat(bind.getPath()).isEqualTo("/tmp/shm")); + } }