Fetch headless Chromium at container startup instead of build time
Build and push server image / test (push) Successful in 45s
Build and push server image / build-and-push (push) Successful in 4m17s
Build and push server image / deploy (push) Failing after 1m42s

build-and-push failed on the last deploy: chromium-headless-shell's
single ~181MB binary can't be split across Docker layers the way this
project's pip/npm installs were (those are many independently-
installable smaller packages; this is one file), and confirmed-failed
to push past the registry's per-layer size limit.

Moves the `playwright install chromium-headless-shell` step from the
Dockerfile to start.sh, caching into PLAYWRIGHT_BROWSERS_PATH on the
/data volume -- only the very first boot on a fresh volume downloads
it, every boot after that is a no-op check. The image itself no longer
grows by ~262MB, so nothing new gets pushed to the registry at all.
This commit is contained in:
2026-07-31 02:18:36 +00:00
parent 8ea1c53ec3
commit c6dad191fb
3 changed files with 40 additions and 23 deletions
+18 -19
View File
@@ -36,8 +36,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
tzdata fontconfig fonts-dejavu-core nodejs npm \
&& rm -rf /var/lib/apt/lists/*
# EXPERIMENTAL, likely unmergeable as-is -- see below. System libs a
# headless Chromium needs (app/html_render.py, the weather widget's
# EXPERIMENTAL. System libs a headless Chromium needs (app/html_render.py, the weather widget's
# opt-in "modern" render style), trimmed from Playwright's own full
# `install-deps chromium` list to just what a headless (no Xvfb),
# Latin-text-plus-emoji use case needs: dropped xvfb (only needed for a
@@ -74,23 +73,23 @@ RUN pip install --no-cache-dir pypdfium2==5.12.1
RUN pip install --no-cache-dir playwright==1.61.0
RUN pip install --no-cache-dir -r requirements.txt
# KNOWN LIKELY BLOCKER, not resolved by pulling this into its own layer:
# `playwright install chromium-headless-shell` unpacks to ~262MB, and its
# single `chrome-headless-shell` binary alone (measured: 181MB) is one
# file -- unlike the pip/npm splits above (independently-installable
# smaller packages moved into their own layers), a single 181MB file
# can't be divided across multiple <100MB Docker layers by any ordinary
# COPY/RUN restructuring; the whole file lands in whichever layer's diff
# contains it. This almost certainly exceeds the same Cloudflare single-
# blob/layer limit that forced the pip/npm splits elsewhere in this file
# (see their comments) -- an actual push to this project's registry
# hasn't been attempted (would require pushing to `main`, which triggers
# deploy) to confirm, but there is no reason to expect a single 181MB
# blob to fit where combined ~113MB of many small wheels didn't. Needs a
# real resolution (a registry without this limit, hosting the browser
# binary outside the image, etc.) before this branch can actually ship --
# tracked as open, not silently assumed away.
RUN playwright install chromium-headless-shell
# The headless Chromium binary itself is deliberately NOT installed
# here at build time. `playwright install chromium-headless-shell`
# unpacks to ~262MB, and its single `chrome-headless-shell` binary alone
# (measured: 181MB) is one file -- unlike the pip/npm splits above
# (independently-installable smaller packages moved into their own
# layers), a single 181MB file can't be divided across multiple <100MB
# Docker layers by any ordinary COPY/RUN restructuring; the whole file
# lands in whichever layer's diff contains it, which confirmed-failed
# to push to this project's registry (the same Cloudflare single-blob/
# layer limit that forced the pip/npm splits elsewhere in this file --
# see their comments). Fix: start.sh downloads it at container startup
# instead, cached on the /data volume (PLAYWRIGHT_BROWSERS_PATH below)
# so it survives restarts/redeploys and only ever downloads once per
# volume, not once per image layer. Trade-off: first boot on a fresh
# volume needs network access to Playwright's CDN -- true of Immich/
# weather API access too, so not a new requirement for this server.
ENV PLAYWRIGHT_BROWSERS_PATH=/data/.playwright-browsers
# render-service/'s dependencies installed as several separate layers
# rather than one `npm install` covering all of them -- a from-scratch