ego (lite) is just a browser, ego is your personal agent across devices.
Join waitlist
CodexDockerRemote browsernoVNCego (lite)

How to put Codex and a browser in Docker without mixing three different 'remote' products

Sep 21, 202611 min read
Codex CLI in Docker beside a Playwright browser reachable over a bound port

“Remote Codex browser” can describe several different setups: Codex running on another machine, Codex inside Docker, a separate browser container, or a browser you only watch through noVNC. They may all feel remote from the outside, but the code, browser, login state, and network connection can live in very different places.

For isolated or parallel work, Docker is a good fit: Codex can run in one workspace while Playwright provides a separate browser runtime over websocket or noVNC. But some tasks depend on the browser you already use, including existing logins, extensions, or a human taking over MFA. In those cases, ego (lite) keeps the browser local in a visible Chromium Space while Codex or another agent drives it, so you do not have to move your daily browser profile into a container.

This guide shows how to wire the Docker path cleanly, including where Codex and the browser run, how websocket and noVNC connect, what should persist, and which ports should stay private. If you are still choosing between local and remote browser isolation, see sandbox web browser for AI agents. The commands below follow current official and project documentation; we did not run the Docker images on this machine for this article.

Which remote Codex architecture are you building?

Four products answer to 'remote Codex browser,' and only one of them ships a browser. Read the table by the third column: that's the plane your task actually runs on.

NameWhat runsBrowser
Codex RemotePhone or another desktop talks to ChatGPT.app on a hostThe host's Chrome extension or Computer Use, if enabled
Docker Sandboxessbx run codex in a sandbox templateOAuth on the host. Not a VNC browser workspace
CLI imagecodex exec, remote-control start, app-serverNone until you add a browser container
Playwright Dockermcr.microsoft.com/playwright browsersrun-server websocket, optional noVNC desktop

Official Codex Remote and remote connections start on the desktop app, not Docker. Cloud chats use cloud environments with a universal image and setup scripts. Neither is a noVNC lab. If you need Codex plus a headed browser in containers, compose a CLI container and a Playwright container on a private network. That's two containers and one private network, not a single command.

Official Codex Remote docs: start, guide, and review coding tasks from your phone on a connected Mac or Windows PC
Official Codex Remote is a phone talking to a desktop host. The page does not document Docker, noVNC, or port 6080. We did not pair a device.

Which Docker images and containers do you need?

Docker's Codex sandbox guide is the supported one-command path: sbx run codex ~/my-project. Authentication runs on the host. The sandbox doesn't load ~/.codex from the host. That's isolation, not a missing volume.

Official Docker Codex sandbox docs showing sbx run codex authenticates on the host so credentials stay out of the sandbox
Docker Sandboxes keep OAuth on the host. That is not a VNC browser workspace. We did not run sbx or complete sign-in.

If you want a plain image, community packaging such as icoretech/codex-docker publishes GHCR tags that mirror upstream Codex CLI releases, runs as user codex, and documents remote-control start plus an authenticated websocket app-server. Pin the tag, because latest is for trials. This is third-party packaging of upstream binaries, not an OpenAI-published browser workspace.

For the browser, Playwright's Docker guide publishes mcr.microsoft.com/playwright:v1.63.0-noble with browsers and OS deps. The Playwright npm package isn't in the image. Pin the image version to the Playwright version in your tests. Microsoft says the image is for testing and development, not for visiting untrusted sites as root.

docker pull mcr.microsoft.com/playwright:v1.63.0-noble
docker run -it --rm --ipc=host --init \
  mcr.microsoft.com/playwright:v1.63.0-noble /bin/bash

How do you attach a remote browser or noVNC?

Two documented planes. The first is Playwright Server. Start it in the container, then connect from the host or from Codex with a matching Playwright version:

docker run -p 127.0.0.1:3000:3000 --rm --init --ipc=host \
  --workdir /home/pwuser --user pwuser \
  mcr.microsoft.com/playwright:v1.63.0-noble \
  /bin/sh -c "npx -y playwright@1.63.0 run-server --port 3000 --host 0.0.0.0"

Then PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test, or browserType.connect('ws://127.0.0.1:3000/'). Add --add-host=hostmachine:host-gateway if the container must reach servers on the host. Use hostmachine, not localhost, from inside Docker.

OpenCode beside official Playwright Docker Remote Connection docs showing docker run port 3000 and ws://127.0.0.1:3000/
Documented websocket plane. Official docs bind Playwright Server on port 3000. This is the docs page, not a running container.

The headed path is noVNC. Playwright documents GitHub Codespaces with features.desktop-lite.webPort 6080 and forwardPorts 6080. That opens the VNC web viewer so you can watch codegen in the container. It isn't Codex Remote, and it isn't your Chrome profile.

OpenCode beside official Playwright Docker noVNC docs showing forwardPorts 6080 and desktop-lite webPort 6080
Documented headed plane. Official Codespaces config forwards 6080 through desktop-lite. No noVNC desktop was started on this machine.

How should ports and auth be bound?

Bind 3000 and 6080 to 127.0.0.1 on the host unless you terminate TLS at a reverse proxy you control. icoretech documents app-server --listen ws://0.0.0.0:4500 with --ws-auth capability-token and --ws-token-sha256, then a client using --remote-auth-token-env. Their remote-control start command uses a private Unix socket and doesn't publish 4500. Never expose an unauthenticated websocket on a public interface.

Docker Sandboxes keep OAuth on the host so the sandbox never sees the browser login cookie. Copy that idea: secrets stay on the host or in a dedicated secret mount, not in the image. Codex cloud secrets are stripped before the agent phase. Treat a local compose file the same way.

What should persist on volumes?

Persist the repo at /workspace and, if you must, CODEX_HOME for config and logs. Don't mount your daily Chrome profile into a container that visits random URLs. A Playwright user-data-dir volume is a test profile. It won't carry 2FA devices or password-manager OS integration. That's the privacy trade for isolation.

For multi-tenant or CI, start clean: no CODEX_HOME reuse across untrusted jobs, no shared /tmp, reset the Playwright server between customers. Local personal work can reuse a named volume. Those are opposite defaults.

How do you start, debug, and recover?

  1. Confirm docker run hello-world, then pull pinned Codex and Playwright tags.
  2. Start Playwright run-server. curl the websocket host from the host network. Version mismatch is the usual 'browser not found' error.
  3. Start Codex with a workspace mount. If sbx can't see ~/.codex, that's documented, not a bug.
  4. Open noVNC only after 6080 is forwarded. A black screen is often missing --ipc=host or the desktop-lite feature.
  5. If Chromium crashes, retry with --ipc=host and, locally, --cap-add=SYS_ADMIN only while debugging.

Phone Remote failing to see a Docker VM is expected. Pair Remote with a desktop app host, or use SSH from that host into the VM. The QR flow doesn't replace compose.

When should the browser stay on your Mac instead?

Keep a local persistent browser when the task needs an authorized daily login, an extension, or a person to take over MFA. Docker plus Playwright Server is stronger for untrusted pages, clean starts, and parallel tenants. ego (lite) 0.5.0.32, dated 2026-09-12 on the changelog, is that local path: Chromium on the Mac, a visible Space, Take over and Stop. It isn't a cloud sandbox or a VNC cluster. Setup: ego (lite) quick start.

OpenCode beside an ego (lite) Space on playwright.dev/docs/docker with Agent is in control, Take over, and Stop
Local path. The Space stayed on the Playwright Docker docs with Agent is in control, Take over, and Stop. No container was started.

Five needs decide this, and no column wins all five. Read each row as the question you'd ask before picking a plane.

NeedDocker browserego (lite)
Login reuseFresh profile unless you mount oneImport daily Chromium state
IsolationContainer, optional non-root + seccompSpace, not a VM
Multi-tenant / concurrencyMany containersOne machine, several Spaces
Failure replayTraces, volumes, VNC recording if you add itWatch live, take over
Data custodyYou operate the host and registryStays on the Mac

Several Spaces on one Mac is that concurrency row, not a Docker tenant farm. Each Space keeps its own page and control state. It still isn't a VM and not a substitute for many containers.

OpenCode beside ego (lite) showing 3 Spaces, two marked Running: chrome docs click proof and local docker docs
One machine, several Spaces. Two were Running at once: the Chrome docs task and the Playwright Docker docs task. That is parallel local work, not a container cluster.

FAQ

Is Codex Remote the same as Codex in Docker?

No. Remote pairs the mobile or desktop app with a Mac or Windows host. Docker runs a CLI or sandbox image. Pairing a phone to a container requires a desktop app host in the middle.

Where is noVNC in the official Codex image?

Nowhere. Playwright documents noVNC for its Docker/Codespaces image on port 6080. Add that container if you need a headed view.

Can I reuse my Chrome logins in the container?

Not by default, and you usually shouldn't. Mounting a daily profile into an untrusted crawl breaks the isolation you bought Docker for. Keep logins in ego (lite) or a dedicated test profile.

What port should Codex app-server use?

Only if you chose the websocket app-server path. Bind 127.0.0.1 and require a token. remote-control start uses a Unix socket and is the safer default on one machine.

When is a local Space better than this compose file?

When you need the account already on the Mac, visible execution, and takeover. ego (lite) is free to download for that path. Keep Docker for clean, parallel, untrusted runs.