Skip to content

Avoid duplicate /dev/shm bind when reusing BrowserWebDriverContainer#11945

Open
kdelay wants to merge 2 commits into
testcontainers:mainfrom
kdelay:fix/issue-11941-selenium-shm-reuse
Open

Avoid duplicate /dev/shm bind when reusing BrowserWebDriverContainer#11945
kdelay wants to merge 2 commits into
testcontainers:mainfrom
kdelay:fix/issue-11941-selenium-shm-reuse

Conversation

@kdelay

@kdelay kdelay commented Jul 24, 2026

Copy link
Copy Markdown

What

Reusing a BrowserWebDriverContainer (stop, then start again) fails on Linux with:

com.github.dockerjava.api.exception.BadRequestException: Status 400: {"message":"Duplicate mount point: /dev/shm"}

Why

configure() runs on every start(). On non-Windows hosts it appended a /dev/shm bind to the container binds unconditionally. When the same container instance is started more than once (reuse), the bind was added again, producing a duplicate mount point that Docker rejects at create time.

Change

Only add the /dev/shm bind when one is not already present. Applied to both the org.testcontainers.selenium.BrowserWebDriverContainer and its deprecated org.testcontainers.containers.BrowserWebDriverContainer counterpart, which shared the same logic.

Verification

Added BrowserWebDriverContainerReuseTest which calls configure() twice (as a reused container would) and asserts a single /dev/shm bind. It fails on the current code (2 binds) and passes with this change. No Docker daemon is required for the test, as it only exercises the container configuration.

./gradlew :testcontainers-selenium:spotlessCheck :testcontainers-selenium:compileJava :testcontainers-selenium:test --tests "org.testcontainers.selenium.BrowserWebDriverContainerReuseTest" is green.

Fixes #11941

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 testcontainers#11941

Signed-off-by: kdelay <kdelay20@gmail.com>
@kdelay
kdelay requested a review from a team as a code owner July 24, 2026 00:14
@duoduobingbing

duoduobingbing commented Jul 24, 2026

Copy link
Copy Markdown

@kdelay Doesn't that test need a safeguard so that it does not run on Windows. E.g. JUnit's @DisabledOnOs(OS.WINDOWS) at the test?

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).
@kdelay

kdelay commented Jul 24, 2026

Copy link
Copy Markdown
Author

Good catch, thanks. Done in f66bd9e - added @DisabledOnOs(OS.WINDOWS) to the test, since the Windows branch of configure() does not add the /dev/shm bind and the assertion would otherwise fail there.

@renechoi renechoi left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix looks right to me on the mechanism: binds is the only accumulating structure configure() touches (exposedPorts is a LinkedHashSet and the env vars are a Map, so those are already idempotent across repeated configure() calls), and keying the guard on the container-side volume path is the correct axis, since that is exactly what Docker rejects as a duplicate mount point.

One coverage gap, though. The regression test only covers org.testcontainers.selenium.BrowserWebDriverContainer, but the change also patches the deprecated org.testcontainers.containers.BrowserWebDriverContainer — which is the class the issue report actually points at (BrowserWebDriverContainer.java#L224). That second hunk is currently unguarded: if I revert only the deprecated class back to a plain else and leave everything else on this branch untouched, BrowserWebDriverContainerReuseTest still passes. The only other test that touches that class, SeleniumStartTest, starts each container once, so it does not exercise reuse either.

Mirroring the test into org.testcontainers.containers closes it — that test source package already exists in the module:

// modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java
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);
    }
}

I ran this locally against f66bd9e with the JDK 17 toolchain. With the deprecated hunk reverted it fails expected: 1L but was: 2L while the existing selenium test stays green; with the fix in place both pass, and :testcontainers-selenium:spotlessCheck is clean.

Minor nit, take it or leave it: the image tag here is selenium/standalone-chrome:4.10.0, while the other selenium tests use 4.13.0. Nothing is pulled in this test so it makes no functional difference, purely consistency.

Do the maintainers want the deprecated class covered as well, or is leaving it test-free deliberate given it is on the way out?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Cannot reuse Selenium BrowserWebDriverContainers under Linux

3 participants