Skip to content

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

Open
kdelay wants to merge 4 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 4 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() (GenericContainer#doStart). 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. getBinds().add(...) has exactly two production call sites in the repository, and both are these.

Scope of the guard

The guard skips the built-in bind whenever some bind already targets the /dev/shm container path, so it is worth showing exactly which inputs change. Probed on main and on this branch with the same five cases (JDK 17.0.15, modules/selenium), printing the resulting bind list:

case main this branch
plain, one configure() /dev/shm:/dev/shm:rw unchanged
reused, two configure() calls /dev/shm:/dev/shm:rw twice one bind
caller-supplied /dev/shm bind, withFileSystemBind("/tmp/shm", "/dev/shm", READ_ONLY) /tmp/shm:/dev/shm:ro plus /dev/shm:/dev/shm:rw /tmp/shm:/dev/shm:ro only
unrelated caller bind on /tmp/other caller bind plus /dev/shm:/dev/shm:rw unchanged
withSharedMemorySize(64MB) no bind unchanged

Only the two rows that produce a duplicate /dev/shm mount point change; the other three are identical. The caller-supplied case is the same Duplicate mount point: /dev/shm failure without any reuse involved, so it gets its own test method instead of being left implicit.

Verification

BrowserWebDriverContainerReuseTest (one copy per package, mirroring the two container classes) calls configure() the way a reused container would and asserts a single /dev/shm bind, plus asserts that a caller-supplied bind survives untouched. No Docker daemon is required; the tests only exercise container configuration.

Reverting just the one-line guard in both classes and leaving the tests in place makes all four tests fail (expected: 1L but was: 2L, and the caller-supplied assertion on singleElement()); restoring it makes them pass.

./gradlew :testcontainers-selenium:spotlessCheck :testcontainers-selenium:test --tests "*BrowserWebDriverContainerReuseTest"

is green (4 tests, 0 failures).

Fixes #11941

Summary by CodeRabbit

  • Bug Fixes

    • Prevented duplicate shared-memory mounts when reusing browser containers.
    • Preserved existing, caller-provided shared-memory mounts during configuration.
  • Tests

    • Added coverage for repeated container configuration and custom shared-memory mounts.

@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?

@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?

@kdelay

kdelay commented Jul 26, 2026

Copy link
Copy Markdown
Author

Thanks, that gap is real and I reproduced it before touching anything: reverting only the org.testcontainers.containers hunk back to a plain else, with the rest of the branch untouched, leaves org.testcontainers.selenium.BrowserWebDriverContainerReuseTest green. So that hunk had no regression coverage at all, and it is the class the issue report points at.

Done in ab77082 - mirrored the test into org.testcontainers.containers, and bumped the tag in the existing test to 4.13.0 to match the rest of the module.

Verified locally with the JDK 17 toolchain: with the deprecated hunk reverted the mirrored test fails expected: 1L but was: 2L while the selenium one stays green, with the fix in place both pass, and :testcontainers-selenium:spotlessCheck is clean.

If covering the deprecated class is not wanted given that it is on the way out, I am happy to drop the mirrored test and keep the production change as is.

kdelay and others added 4 commits September 5, 2026 14:29
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>
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).
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 <kdelay20@gmail.com>
Co-authored-by: renechoi <renechoi90@gmail.com>
@kdelay
kdelay force-pushed the fix/issue-11941-selenium-shm-reuse branch from e4fce60 to 7e3aea6 Compare September 5, 2026 05:32
@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 74e5f308-2b4c-46a6-9eb7-373972cb1fd7

📥 Commits

Reviewing files that changed from the base of the PR and between a4d3a03 and 7e3aea6.

📒 Files selected for processing (4)
  • modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java
  • modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java
  • modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java
  • modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The Selenium browser container now checks for an existing /dev/shm bind before adding one on non-Windows systems. New reuse tests cover repeated configuration and preservation of caller-supplied binds.

Changes

Selenium shared-memory bind reuse

Layer / File(s) Summary
Prevent duplicate shared-memory binds
modules/selenium/src/main/java/org/testcontainers/containers/BrowserWebDriverContainer.java, modules/selenium/src/main/java/org/testcontainers/selenium/BrowserWebDriverContainer.java
Non-Windows configuration adds the default /dev/shm bind only when no existing bind targets /dev/shm.
Validate bind reuse behavior
modules/selenium/src/test/java/org/testcontainers/containers/BrowserWebDriverContainerReuseTest.java, modules/selenium/src/test/java/org/testcontainers/selenium/BrowserWebDriverContainerReuseTest.java
Tests verify that repeated configure() calls do not duplicate the bind and that caller-supplied read-only binds remain unchanged.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 7e3ae

The change prevents duplicate /dev/shm mounts when Selenium browser containers are restarted, while retaining caller-provided shared-memory binds and existing Windows behavior. No actionable current-head merge risk remains.

Suggested reviewers: eddumelendez, kiview

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: preventing duplicate /dev/shm binds when reusing BrowserWebDriverContainer.
Description check ✅ Passed The description explains the failure, root cause, production changes, scope, regression tests, verification command, and linked issue. It satisfies the repository template requirements.
Linked Issues check ✅ Passed The changes address issue #11941 by preventing duplicate /dev/shm mounts during repeated starts on Linux. They preserve explicit shared-memory configuration and cover both current and deprecated conta…
Out of Scope Changes check ✅ Passed All changes are directly related to fixing duplicate /dev/shm mounts and adding regression coverage for the linked issue. No unrelated changes are present.
  • Fix all pre-merge checks with AI

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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