Microsoft's own Playwright image carries all three engines at 3.5 GB; this
server calls chromium.launch and nothing else, ever. Node's own slim base plus
Chromium installed on its own comes to 1.84 GB - most of that is the OS
libraries --with-deps pulls in for a sandboxed Chromium to run at all, not the
browser binary itself.
One mistake made and caught while building this: installing under
HOME=/tmp/browser-home, which is gone the instant the container starts, because
/tmp is mounted as tmpfs. Moved to PLAYWRIGHT_BROWSERS_PATH=/ms-playwright,
outside it - which is also where Microsoft's own image keeps browsers, and for
the same reason.
Verified under the production security constraints, not assumed to still hold
on a different base: seccomp profile, cap_drop ALL plus cap_add SYS_CHROOT,
read-only root, tmpfs /tmp, chromiumSandbox: true. Chromium launched sandboxed
and navigated a real page under all of them together.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
They were three folders on one laptop: a coding agent with a git history of its
own, and two servers - a development server and a browser - with none at all.
What makes them a stack is what sits between them, and that lived nowhere: the
compose file, the gateway, the egress proxy and the networks that keep the worker
off the internet. So the whole thing is one repository, and the coding agent's
separate history is folded into it rather than kept alongside.
What is deliberately absent: .env, node_modules, and the live service
definitions. The .example files next to them say what belongs there.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>