Skip to content

Shrink Docker images with scratch runtimes and stripped binaries - #330

Open
mxschmitt wants to merge 4 commits into
mainfrom
cursor/smaller-docker-images-ba69
Open

Shrink Docker images with scratch runtimes and stripped binaries#330
mxschmitt wants to merge 4 commits into
mainfrom
cursor/smaller-docker-images-ba69

Conversation

@mxschmitt

@mxschmitt mxschmitt commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Summary

Each Dockerfile was reviewed independently for size. Runtime behavior is unchanged: workers still include Chromium, Firefox, and WebKit; Caddy still reverse-proxies /service/ and /file-uploads/.

Measured against ghcr.io/mxschmitt/try-playwright/<name>:latest after a local rebuild:

Image Before After Saved
control-service 118MB 67.2MB 43%
file-service 35.4MB 13.7MB 61%
log-aggregator 28MB 8.98MB 68%
frontend 104MB 82.1MB 21%
squid 37.4MB 37.4MB already minimal
worker-javascript 3.63GB 2.41GB 34% (1.22GB)

Go services (control-service, file-service, log-aggregator)

  • Final stage is scratch instead of alpine:latest + ca-certificates.
  • Binaries are built with -trimpath -ldflags="-s -w".
  • CA bundle, /etc/passwd, and /tmp are copied from the Alpine builder.

Frontend

  • Playwright component-test browsers are skipped during npm ci.
  • Runtime is the official static Caddy binary on scratch.

Squid

  • Already a single Alpine + squid package.

worker-javascript

  • Replaced mcr.microsoft.com/playwright:noble (~3.4GB Ubuntu) with node:24-bookworm-slim.
  • Installs only chromium-headless-shell, Firefox, WebKit, and ffmpeg. Headed Chromium and WebKit GTK are unused in this headless playground.
  • Test runner is invoked as playwright test from PATH.

Tried slimtoolkit/slim (mint 1.41.8) on the 2.41GB image: Chromium/Firefox/WebKit still launched, but the minified image was larger (2.62GB). The Dockerfile already removed the dead weight, so the tracer had little to delete and flattening plus --include-shell added overhead. Not wired into CI.

Other workers (python, java, csharp)

  • Flatten/cache/skip-download on the official language images.

Test plan

  • Compare stripped vs unstripped Go binaries
  • go test ./... and go build ./...
  • Rebuild control, file, log-aggregator, frontend, squid and compare sizes
  • Smoke-run those images
  • Rebuild worker-javascript on Debian slim (2.41GB) and launch Chromium, Firefox, WebKit, and Chromium PDF
  • Evaluate slimtoolkit/mint: works with Docker API 1.44, but produced a larger image
Open in Web Open in Cursor 

cursoragent and others added 2 commits September 4, 2026 05:21
Go services ship from scratch with CA certs instead of Alpine, and all
Go binaries are built with -trimpath -ldflags=-s -w. Workers skip a
second Playwright browser download, drop unused packages, and flatten
so those deletions actually leave the image. Frontend serves the Vite
build with the static Caddy binary on scratch.

Co-authored-by: Max Schmitt <max@schmitt.mx>
Classic docker build on some hosts rejects COPY --chmod. The entrypoint
is already executable in git, so a normal COPY is enough.

Co-authored-by: Max Schmitt <max@schmitt.mx>
@mxschmitt
mxschmitt marked this pull request as ready for review September 4, 2026 05:34
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T05:37:35.454978Z f1ff0c2 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

cursoragent and others added 2 commits September 4, 2026 05:52
Replace the 3.4GB official Playwright Ubuntu image with node:24-bookworm-slim
and install only chromium-headless-shell, Firefox, WebKit, and ffmpeg.
Headed Chromium and WebKit GTK are unused in this headless playground.
Invoke the Playwright test runner from PATH instead of a hard-coded
global node_modules path.

Co-authored-by: Max Schmitt <max@schmitt.mx>
node:bookworm-slim already has the node user at uid 1000, so a hardcoded
pwuser uid fails useradd.

Co-authored-by: Max Schmitt <max@schmitt.mx>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants