Engineering

Cutting the Docker Image to 1.4 GB

Part seven of building oo-workers in public: trimming the image from 3.5 GB to 1.4 GB with a headless Chromium shell, and where the hard floor is.

ObserveOne Team
2 min read

In this series

Building oo-workers in public

  1. 1.How We Built a Self-Hosted Monitoring Engine
  2. 2.Eight Monitor Types From One Engine
  3. 3.Building the Dashboard Without a Framework
  4. 4.A Portable Backup Format, Not pg_dump
  5. 5.A Three-Pass Code Audit in 14 PRs
  6. 6.Killing the 5-Second Poll
  7. 7.Cutting the Docker Image to 1.4 GB
  8. 8.Tests That Spin Real Databases
  9. 9.The Alert That Never Fired

oo-workers ships as a Docker image, and the image was big: around 3.5 GB. Version 1.28.6 cut it to about 1.4 GB without dropping a feature. Here is where the weight was.

Where the weight was#

The bulk was Playwright. To run browser checks, the image bundled Playwright's full browser set: Chromium, Firefox, and WebKit. But the runner only ever launches headless Chromium. So we install just the Chromium headless shell and skip the other two browsers entirely. That, plus shipping production-only dependencies (dropping the test and build toolchain) and running as a non-root user, took the master and QA-agent images from ~3.49 GB to ~1.43 GB, and the light agent from 363 MB to 226 MB.

The Bun and Node detail#

One wrinkle. The engine runs on Bun, but Playwright's test runner spawns its worker processes with node, and Bun's node-compatibility shim does not carry Playwright's worker IPC. So the browser images install real Node.js alongside Bun, and the code calls node node_modules/.bin/playwright directly rather than npx, which is not in the Bun base image. Bun runs the app, Node runs Playwright's workers, and they coexist in the same image.

The floor#

There is a floor. Even stripped to the headless shell, Chromium pulls in a chain of system libraries (graphics, fonts, and the rest), so about 1.43 GB is as small as the browser image gets without giving up browser checks. The light agent, which carries no browser at all, sits at 226 MB.

The trade-off#

Only the Chromium headless shell ships. A browser-check script that targets Firefox or WebKit, or asks for a headed browser, will fail, and the dashboard offers no browser picker. For unattended monitoring that runs headless from a server, that is the right cut: pay for the one browser you use, not the two you do not.

The change was validated against the deployed images, not just the build: the full UI end-to-end suite and the multi-region harness both ran on the slim agent images, with a real browser check reaching a passing state.

Weighing your options on this stack?

Drop into the head-to-head pages, or browse the alternatives we recommend.

Alternatives shortlists

Ready for AI-Powered Testing?

ObserveOne monitors your selectors 24/7 and automatically heals them when websites change. Never deal with broken tests again.

Start Free Trial