Fetch headless Chromium at container startup instead of build time
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:
+10
-4
@@ -283,10 +283,16 @@ widgets on the same frame without a Floyd-Steinberg seam at the boundary
|
||||
(see that module's docstring for why ordered dithering doesn't have this
|
||||
problem and Floyd-Steinberg does) -- no `Frame`-level dithering setting
|
||||
was needed. Playwright/Chromium is a real, heavyweight runtime dependency
|
||||
imported lazily only when a weather widget actually uses this style, and
|
||||
its Docker packaging has a known likely-blocking image-size problem not
|
||||
yet resolved (see `server/Dockerfile`'s own comment) -- treat this style
|
||||
as unshipped/local-only until that's sorted out.
|
||||
imported lazily only when a weather widget actually uses this style.
|
||||
Its browser binary is fetched by `start.sh` at container startup rather
|
||||
than baked into the image (see `server/Dockerfile`'s own comment) --
|
||||
a single ~181MB `chrome-headless-shell` binary can't be split across
|
||||
Docker layers the way this project's pip/npm installs were, and
|
||||
confirmed-failed to push to the registry as a build-time layer; cached
|
||||
on the `/data` volume (`PLAYWRIGHT_BROWSERS_PATH`) so only the very
|
||||
first boot on a fresh volume actually downloads it. Still real-panel-
|
||||
unverified (see this widget's own render_style rollout notes/PR) --
|
||||
treat "modern" style as experimental regardless of deploy status.
|
||||
|
||||
`current`/`hourly`/`daily` share one configured location
|
||||
(`city_label`/`city_latitude`/`city_longitude`, set via `POST .../
|
||||
|
||||
+18
-19
@@ -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
|
||||
|
||||
@@ -5,6 +5,18 @@
|
||||
# Then execs uvicorn as the foreground/PID 1 process so it receives
|
||||
# Docker's stop signal directly.
|
||||
#
|
||||
# Before either: fetch headless Chromium (app/html_render.py, the
|
||||
# weather widget's opt-in "modern" render style) into
|
||||
# PLAYWRIGHT_BROWSERS_PATH (set in the Dockerfile to a path on the /data
|
||||
# volume) if it isn't already cached there -- see the Dockerfile's own
|
||||
# comment for why this happens at startup instead of build time. Only
|
||||
# the very first boot on a fresh volume actually downloads anything;
|
||||
# every boot after that is a no-op ls check.
|
||||
if [ -z "$(ls -A "$PLAYWRIGHT_BROWSERS_PATH" 2>/dev/null)" ]; then
|
||||
echo "Fetching headless Chromium into $PLAYWRIGHT_BROWSERS_PATH (first boot on this volume)..." >&2
|
||||
playwright install chromium-headless-shell
|
||||
fi
|
||||
#
|
||||
# Wrapped in a restart loop, not a bare `node ... &`: a bare background
|
||||
# process that crashes stays dead for good, with nothing to bring it
|
||||
# back -- turning any single render crash (a not-yet-found jsdom/
|
||||
|
||||
Reference in New Issue
Block a user