PRACTICAL GUIDE / Selenium Grid dynamic Docker nodes

Run Selenium Grid Dynamic Nodes with Per-Session Docker Containers

Configure Selenium Grid dynamic Docker nodes to launch isolated browser containers per session with pinned images, secure daemon access, and clean teardown.

By The Testing AcademyUpdated July 11, 20269 min read
All field guides
In this guide11 sections
  1. Understand the per-session container path
  2. Map images to minimal stereotypes
  3. Pin controller and child environments together
  4. Launch the controller with deliberate mounts
  5. Send capabilities that match exactly what is offered
  6. Control child-container readiness and pressure
  7. Preserve evidence before the container disappears
  8. Diagnose failures by the last successful boundary
  9. Weigh isolation against startup and privilege cost
  10. Dynamic Grid readiness checklist
  11. Make disposability provable

What you will learn

  • Understand the per-session container path
  • Map images to minimal stereotypes
  • Pin controller and child environments together
  • Launch the controller with deliberate mounts

Selenium Grid dynamic Docker nodes turn a new-session request into a short-lived browser environment. Instead of keeping a fixed browser process available on a long-running node, Grid matches capabilities to a configured image, creates one child container for the session, proxies WebDriver commands to it, and removes it after teardown.

That isolation is valuable only when image selection, daemon access, capacity, readiness, and cleanup are engineered as one system. A dynamic node with floating images or an overcommitted host merely trades persistent-browser drift for container-start failures. The configuration must make the environment reproducible and the failure boundaries observable.

Understand the per-session container path

The official Grid TOML guide describes a Standalone or Node configuration that maps stereotypes to Docker images and connects to a Docker daemon. The Node remains part of Grid; the selected standalone browser image is the disposable execution environment.

Animated field map

Dynamic Grid Session Container

A queued request is matched to an advertised stereotype, mapped to an approved image, executed in a child container, and then removed.

  1. 01 / session request

    Session Request

    The client submits standard and namespaced capabilities to Grid.

  2. 02 / slot match

    Grid Slot Match

    The Distributor selects a free slot whose stereotype satisfies the request.

  3. 03 / image selection

    Docker Image Selection

    The matched stereotype maps to one pinned browser image reference.

  4. 04 / browser container

    Ephemeral Browser Container

    A child standalone container owns the browser and WebDriver session.

  5. 05 / session teardown

    Session Teardown

    Grid closes the child session, retains required evidence, and removes the container.

There are two startup delays to distinguish. Grid may wait for a compatible dynamic slot, then the Docker-backed node must create a child container and wait for its WebDriver service. A queue timeout and a child-server startup timeout diagnose different capacity problems and should remain separate in monitoring.

Map images to minimal stereotypes

Disable local driver detection so the node advertises only the intentionally configured dynamic environments. Each configs entry is an image followed by a JSON stereotype string. This file is a deployment template: the release process must replace the digest tokens with real approved image digests before Grid starts.

TOML
[node]
detect-drivers = false
max-sessions = 4
session-timeout = 300

[docker]
configs = [
  "selenium/standalone-chrome@sha256:CHROME_IMAGE_DIGEST", "{\"browserName\": \"chrome\", \"platformName\": \"linux\"}",
  "selenium/standalone-firefox@sha256:FIREFOX_IMAGE_DIGEST", "{\"browserName\": \"firefox\", \"platformName\": \"linux\"}"
]
url = "http://127.0.0.1:2375"
assets-path = "/opt/selenium/assets"
host-config-keys = ["Binds"]

Keep stereotypes as small as the scheduling contract allows. Adding a browser version, platform, or custom capability changes matching. Advertise it only when the child image actually guarantees it and clients genuinely need to request it. A decorative custom field that clients omit can make every otherwise valid request unmatched.

The four-session value is illustrative, not a recommendation. Capacity must fit CPU, memory, shared-memory, disk, network, and application pressure on the worker. A child container boundary does not create physical resources.

Pin controller and child environments together

Use an immutable tag or digest for the node-docker or standalone-docker controller and every child browser image. Promote those references through the same review as Selenium dependencies. The official docker-selenium Dynamic Grid documentation shows the supported controller images and their expected config mount.

Do not label an image latest in a release Grid. A later pull can change the browser, driver, operating-system packages, or Grid-side behavior while the tests remain unchanged. Record the resolved controller digest and selected child digest in session evidence so a failed rerun can reproduce the environment.

Maintain separate mappings when different browser channels or policies are required. A beta image should have a distinct stereotype that a test explicitly requests; it should not silently satisfy the same contract as the stable release environment.

Launch the controller with deliberate mounts

A Standalone Dynamic Grid is useful for a contained worker. The Compose fragment below shows the ownership boundaries without claiming that environment substitution occurs inside TOML. The rendered docker.toml already contains final image references.

YAML
services:
  dynamic-grid:
    image: selenium/standalone-docker@sha256:CONTROLLER_IMAGE_DIGEST
    ports:
      - "4444:4444"
    environment:
      SE_NODE_DOCKER_CONFIG_FILENAME: docker.toml
    volumes:
      - ./docker.toml:/opt/selenium/docker.toml:ro
      - ./grid-assets:/opt/selenium/assets
      - /var/run/docker.sock:/var/run/docker.sock

The Docker socket mount is the most sensitive line. A process that can control the daemon can create privileged containers, mount host paths, and inspect other workloads. Place this service on a dedicated, access-controlled worker. Do not expose the daemon over an unauthenticated network socket. If a protected remote daemon is required, apply its TLS and authorization model and verify what Grid's Docker client supports.

Mount the rendered configuration read-only. Give the assets directory only the permissions and retention it requires. Avoid passing broad host binds into children; host-config-keys explicitly controls which parent host settings may propagate.

Send capabilities that match exactly what is offered

Clients should request the smallest acceptable environment. The following Java setup asks Grid for Linux Chrome and adds a diagnostic name. It does not request an arbitrary version that the stereotype never advertised.

Java
import java.net.URI;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;

ChromeOptions options = new ChromeOptions();
options.setPlatformName("linux");
options.setCapability("se:name", "checkout-dynamic-container");

WebDriver driver = new RemoteWebDriver(
    URI.create(System.getenv("SELENIUM_GRID_URL")).toURL(),
    options);
try {
  driver.get("https://test.example.internal/checkout");
  // Execute assertions through the disposable child container.
} finally {
  driver.quit();
}

If either browser is acceptable, use a supported Selenium capability-negotiation API deliberately or create separate matrix jobs. Do not send ambiguous vendor options for multiple browsers in one object. The selected stereotype should explain why one image was chosen.

Control child-container readiness and pressure

Image pull time, container creation, WebDriver startup, and browser startup all occur before the client receives a session. Pre-pull approved images on the worker or use a controlled registry cache when cold pulls exceed the setup budget. Monitor each stage rather than increasing the overall client timeout blindly.

Set the node's max-sessions from measured host behavior. Test a representative heavy page, video or artifact policy, and peak concurrent startup. Starting four browsers at once can stress the host differently from running four already-started sessions. A lower concurrency with predictable startup often produces more completed tests than a nominally larger but unstable pool.

Child containers also need adequate shared memory and process handling. Use settings supported by the official image and Dynamic Grid host configuration rather than adding browser flags that disable safeguards. Validate DNS, certificates, proxy access, and routes from the child container, not only from the controller.

Preserve evidence before the container disappears

Ephemeral execution removes the filesystem that contains browser and driver logs unless evidence is exported. Decide which assets are retained, where they are written, and what event marks them complete. The configured assets path is a natural handoff location, but tests and operations still need naming, access, and expiry rules.

Always record WebDriver session id, test id, requested capabilities, returned capabilities, controller digest, child image digest, container id, start latency, and teardown result. Redact credentials and application secrets. This metadata distinguishes image-selection errors from browser crashes and product assertions.

Do not retain all videos or verbose logs indefinitely. Use failure-focused capture where supported and preserve enough startup logs to diagnose a child that never became ready. If artifact upload happens asynchronously, teardown must not delete the child before the required files are safely handed off.

Diagnose failures by the last successful boundary

An unmatched request indicates a capability and stereotype problem. Inspect the serialized request and advertised Grid stereotypes before checking Docker. A matched slot followed by an image error points to an invalid reference, registry authentication, missing image, or daemon connectivity. A created container that never becomes ready points to child logs, resource limits, network setup, or browser startup.

A session that works but leaves containers behind points to teardown, controller interruption, or Docker cleanup. Compare Grid's session map with daemon containers and alert on orphans by controller labels rather than deleting unknown containers. A test timeout with a healthy session belongs to the application or test layer, not to dynamic provisioning.

Repeated failures across both browser images suggest controller or host infrastructure. A failure isolated to one mapping suggests its image, stereotype, or browser-specific startup. Preserve the selected mapping in every error so operators do not have to infer it from the requested browser name.

Weigh isolation against startup and privilege cost

Per-session containers reset browser profiles, processes, and filesystem state cleanly. They also add image management, startup latency, Docker-daemon privilege, and artifact handoff. Fixed nodes may be simpler when workers are already disposable and startup speed dominates. Dynamic nodes are stronger when session isolation and reproducible images justify the control plane.

Do not use container churn as a substitute for test isolation. Tests must still own accounts, data, and teardown. Likewise, a dynamic browser container does not isolate a shared application environment from parallel writes.

Dynamic Grid readiness checklist

  • Disable local driver detection on a Docker-backed dynamic node.
  • Render image-to-stereotype pairs with immutable approved references.
  • Keep stereotypes minimal and aligned with actual image capabilities.
  • Pin and record both controller and child image digests.
  • Protect Docker daemon access on a dedicated worker.
  • Mount configuration read-only and restrict propagated host settings.
  • Size max-sessions from measured startup and steady-state pressure.
  • Verify DNS, TLS, proxy, and application routes from child containers.
  • Export required artifacts before child removal.
  • Call driver.quit in guaranteed test teardown.
  • Alert on unmatched requests, startup failures, and labeled orphan containers separately.

Make disposability provable

A dynamic Grid is production-ready when every session has an explainable stereotype match, an immutable image, bounded host resources, retained failure evidence, and a confirmed teardown. Build those controls before increasing concurrency. Then a disposable browser container becomes a reproducible test boundary instead of an opaque extra layer between the test and its failure.

// LIVE COURSE / THE TESTING ACADEMY

Playwright Automation Mastery

Go beyond Selenium. Master Playwright with JS/TS in 90 days.

From the instructor behind this guide.

Playwright jobs are growing 8x faster than Selenium. 90 days / 75+ live hrs / Tue-Thu-Sat 7 AM IST.

Code PROMODE / 10% offJoin the batch

The Testing Academy editorial desk

Practical QA guidance built around test evidence, production tradeoffs, and interview-ready explanations.

Published July 11, 2026 / Reviewed July 11, 2026

PRIMARY REFERENCES

Verify the details at the source

QABattle guides are practical explanations. Product behavior, standards, and APIs can change, so use these primary references for the canonical details.

  1. 01
    Selenium documentation

    Selenium Project

    Canonical WebDriver, Grid, waits, element, and browser automation guidance.

  2. 02
    WebDriver standard

    W3C

    The browser automation protocol specification behind WebDriver implementations.

FAQ / QUICK ANSWERS

Questions testers ask

What makes a Selenium Grid Docker node dynamic?

The node selects a configured browser image for a matching new-session request, starts a dedicated container for that session, and removes the container when the session ends.

How does Dynamic Grid choose a browser container image?

The `[docker].configs` array maps each image reference to a JSON stereotype. Grid capability matching selects a compatible stereotype, and that mapping determines the image used for the child container.

Should Dynamic Grid use floating Docker image tags?

No for controlled CI. Promote an exact tag or digest and update the controller and child-image mappings deliberately so reruns do not acquire an unreviewed browser environment.

Why is mounting the Docker socket a security concern?

Access to the Docker daemon grants powerful host-level container operations. Run the dynamic controller on a dedicated worker, restrict network and filesystem exposure, and do not mix it with untrusted workloads.

What happens when a test never calls driver.quit?

Grid can eventually reclaim an inactive session according to node timeout policy, but relying on that delays slot and container cleanup. Every fixture should call `quit` in a guaranteed teardown path.