How to Expose Chromium’s Remote Debugging Port to the Outside from Within a Docker Container

2026-01-09 12:03 (17 hours ago) ytyng

This article explains how to make the remote debugging port (9222) of a Chromium browser running inside a Docker container accessible from the host machine or other containers.

Background

In E2E testing environments using Selenium Grid or Playwright, it’s common to run browsers inside Docker containers. If you want to use the Chrome DevTools Protocol (CDP) for debugging or automation, you need external access to the remote debugging port.

Normally, passing --remote-debugging-port=9222 and --remote-debugging-address=0.0.0.0 to Chromium should allow access from outside, but in recent versions this no longer works.

Problem

Even if you start Chromium with the following options, you cannot connect from outside:

chromium \
    --remote-debugging-port=9222 \
    --remote-debugging-address=0.0.0.0 \
    --no-sandbox \
    about:blank

When you check inside the container, it’s listening on 127.0.0.1:9222 instead of 0.0.0.0:9222:

$ netstat -tlnp | grep 9222
tcp  0  0  127.0.0.1:9222  0.0.0.0:*  LISTEN  11/chromium

Cause

From Chromium M113/M114 onward, for security reasons, --remote-debugging-address=0.0.0.0 is internally forced to 127.0.0.1.

Chromium’s source code includes logic like the following:

// headless/lib/headless_browser_main_parts.cc
if (remote_debugging_address.IsIPv4AllZeros()) {
    remote_debugging_address = net::IPAddress::IPv4Localhost();
} else if (remote_debugging_address.IsIPv6AllZeros()) {
    remote_debugging_address = net::IPAddress::IPv6Localhost();
}

The reasoning is that the remote debugging port is a powerful feature that allows full control of the browser, and exposing it to a network is a serious security risk.

This is also reported in Chromium’s Bug Tracker (Issue 1425667), but the status is “WontFix,” meaning it’s treated as an intentional behavior change.

Solution

The official workarounds recommended by Chromium are:

  1. SSH tunneling
  2. Reverse proxy (nginx, socat, etc.)
  3. VPN

In Docker environments, SSH tunneling is not very practical, so the simplest solution is port forwarding using socat.

Implementation steps

1. Add socat to your Dockerfile

FROM debian:trixie-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
    chromium \
    socat \
    # ... other required packages
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

2. Change Chromium’s debugging port to an internal-only port

Since Chromium will only listen on 127.0.0.1, use an internal port (e.g., 9223):

# start-chrome.sh
exec /usr/lib/chromium/chromium \
    --remote-debugging-port=9223 \
    --remote-allow-origins=* \
    --no-sandbox \
    --disable-gpu \
    about:blank

3. Configure port forwarding with socat

Use socat to forward from 0.0.0.0:9222 to 127.0.0.1:9223.

Example configuration when using supervisord:

[program:chromium]
command=/usr/local/bin/start-chrome.sh
autostart=true
autorestart=true

[program:socat-debug]
command=/usr/bin/socat TCP-LISTEN:9222,fork,reuseaddr TCP:127.0.0.1:9223
autostart=true
autorestart=true

4. Expose the port in Docker

docker run -p 9222:9222 your-image

Verification

After starting the container, you can verify from the host machine with:

$ curl -s http://127.0.0.1:9222/json
[ {
   "description": "",
   "devtoolsFrontendUrl": "https://chrome-devtools-frontend.appspot.com/...",
   "id": "...",
   "title": "about:blank",
   "type": "page",
   "url": "about:blank",
   "webSocketDebuggerUrl": "ws://127.0.0.1:9222/devtools/page/..."
} ]

If JSON is returned, it’s working.

Notes for Apple Silicon Macs

When using Docker on Apple Silicon (M1/M2/M3) Macs, extra care is required.

If you build an x86_64 image by specifying --platform linux/amd64, emulation will be done via Rosetta 2. However, Chromium requires the SSE3 instruction set and will not run properly under Rosetta:

The hardware on this system lacks support for the sse3 instruction set.

For local development, you need to build natively for ARM64, and only build for x86_64 for production deployment:

# For local development (ARM64)
docker build -t my-image .

# For production deployment (x86_64)
docker build --platform linux/amd64 -t my-image .

Summary

This change is an intentional security hardening in Chromium, and it’s unlikely to be reverted in the future.

Currently unrated
The author runs the application development company Cyberneura.
We look forward to discussing your development needs.

Archive

2026
2025
2024
2023
2022
2021
2020
2019
2018
2017
2016
2015
2014
2013
2012
2011