Free preview. Full chapter — production Dockerfile, docker-compose.yml, Chrome flag reference — in the Production Guide.

Docker Production Setup for Browser Use

Running Browser Use directly on your laptop works fine — until it doesn't. The moment you need reproducible builds, multiple concurrent agents, or deployment to a CI pipeline, Docker stops being optional. It solves three concrete problems: dependency isolation (no more "works on my machine"), resource containment (Chromium memory leaks don't take down your entire server), and horizontal scaling (spin up N identical agent containers with one command).

The hard part isn't Docker itself — it's Chromium inside Docker. Chrome expects a real display server, real GPU drivers, and a real user namespace. Inside a container, none of those exist by default. The three flags you will see in every working Browser Use Docker setup are: --no-sandbox (disables the SUID sandbox, required because containers run as root by default), --disable-dev-shm-usage (forces Chrome to use /tmp instead of /dev/shm, which Docker limits to 64MB by default), and --disable-gpu (skips GPU initialization entirely). Without these three flags, Chrome will either crash on startup or hang silently. This is exactly what GitHub Issue #2513 documents — dozens of users with perfectly working local setups that break the moment they go into Docker, all because of missing Chrome flags and insufficient shared memory.

A production Dockerfile benefits from a multi-stage build. Stage one installs all build dependencies — Python packages, Playwright browsers, system libraries — and produces a cache-heavy layer you never ship. Stage two copies only the runtime artifacts: the virtual environment, the Playwright browser binaries, and your application code. The result is an image that's 30-40% smaller than a single-stage build and doesn't carry build tooling that an attacker could exploit. For the Playwright browsers specifically, use playwright install-deps chromium in the build stage to pull in the exact system library versions Chromium needs, then copy ~/.cache/ms-playwright to the final stage.

The health check matters more than you think. Chromium can appear to be running while its renderer process has crashed. A simple curl http://localhost:9222/json/version against Chrome's DevTools debugging port tells you whether the browser is actually alive and accepting connections. Run this on a 30-second interval with a 10-second timeout to catch silent failures before your task queue feeds work to a dead agent.

# docker-compose.yml — Browser Use agent with health check
version: "3.9"
services:
  browser-agent:
    build:
      context: .
      dockerfile: Dockerfile
    shm_size: "2gb"
    environment:
      - DISPLAY=:99
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
    ports:
      - "9222:9222"
    volumes:
      - ./profiles:/app/profiles
      - ./tasks:/app/tasks
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9222/json/version"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 15s
    restart: unless-stopped
🔒

Unlock the full chapter. Get the complete production Dockerfile with multi-stage build, full Chrome flag reference with explanations, docker-compose.yml with Xvfb sidecar, and a debugging checklist for the 5 most common Docker-specific failures.

Get the Production Guide — $39