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
|
(see that module's docstring for why ordered dithering doesn't have this
|
||||||
problem and Floyd-Steinberg does) -- no `Frame`-level dithering setting
|
problem and Floyd-Steinberg does) -- no `Frame`-level dithering setting
|
||||||
was needed. Playwright/Chromium is a real, heavyweight runtime dependency
|
was needed. Playwright/Chromium is a real, heavyweight runtime dependency
|
||||||
imported lazily only when a weather widget actually uses this style, and
|
imported lazily only when a weather widget actually uses this style.
|
||||||
its Docker packaging has a known likely-blocking image-size problem not
|
Its browser binary is fetched by `start.sh` at container startup rather
|
||||||
yet resolved (see `server/Dockerfile`'s own comment) -- treat this style
|
than baked into the image (see `server/Dockerfile`'s own comment) --
|
||||||
as unshipped/local-only until that's sorted out.
|
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
|
`current`/`hourly`/`daily` share one configured location
|
||||||
(`city_label`/`city_latitude`/`city_longitude`, set via `POST .../
|
(`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 \
|
tzdata fontconfig fonts-dejavu-core nodejs npm \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# EXPERIMENTAL, likely unmergeable as-is -- see below. System libs a
|
# EXPERIMENTAL. System libs a headless Chromium needs (app/html_render.py, the weather widget's
|
||||||
# headless Chromium needs (app/html_render.py, the weather widget's
|
|
||||||
# opt-in "modern" render style), trimmed from Playwright's own full
|
# opt-in "modern" render style), trimmed from Playwright's own full
|
||||||
# `install-deps chromium` list to just what a headless (no Xvfb),
|
# `install-deps chromium` list to just what a headless (no Xvfb),
|
||||||
# Latin-text-plus-emoji use case needs: dropped xvfb (only needed for a
|
# 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 playwright==1.61.0
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# KNOWN LIKELY BLOCKER, not resolved by pulling this into its own layer:
|
# The headless Chromium binary itself is deliberately NOT installed
|
||||||
# `playwright install chromium-headless-shell` unpacks to ~262MB, and its
|
# here at build time. `playwright install chromium-headless-shell`
|
||||||
# single `chrome-headless-shell` binary alone (measured: 181MB) is one
|
# unpacks to ~262MB, and its single `chrome-headless-shell` binary alone
|
||||||
# file -- unlike the pip/npm splits above (independently-installable
|
# (measured: 181MB) is one file -- unlike the pip/npm splits above
|
||||||
# smaller packages moved into their own layers), a single 181MB file
|
# (independently-installable smaller packages moved into their own
|
||||||
# can't be divided across multiple <100MB Docker layers by any ordinary
|
# layers), a single 181MB file can't be divided across multiple <100MB
|
||||||
# COPY/RUN restructuring; the whole file lands in whichever layer's diff
|
# Docker layers by any ordinary COPY/RUN restructuring; the whole file
|
||||||
# contains it. This almost certainly exceeds the same Cloudflare single-
|
# lands in whichever layer's diff contains it, which confirmed-failed
|
||||||
# blob/layer limit that forced the pip/npm splits elsewhere in this file
|
# to push to this project's registry (the same Cloudflare single-blob/
|
||||||
# (see their comments) -- an actual push to this project's registry
|
# layer limit that forced the pip/npm splits elsewhere in this file --
|
||||||
# hasn't been attempted (would require pushing to `main`, which triggers
|
# see their comments). Fix: start.sh downloads it at container startup
|
||||||
# deploy) to confirm, but there is no reason to expect a single 181MB
|
# instead, cached on the /data volume (PLAYWRIGHT_BROWSERS_PATH below)
|
||||||
# blob to fit where combined ~113MB of many small wheels didn't. Needs a
|
# so it survives restarts/redeploys and only ever downloads once per
|
||||||
# real resolution (a registry without this limit, hosting the browser
|
# volume, not once per image layer. Trade-off: first boot on a fresh
|
||||||
# binary outside the image, etc.) before this branch can actually ship --
|
# volume needs network access to Playwright's CDN -- true of Immich/
|
||||||
# tracked as open, not silently assumed away.
|
# weather API access too, so not a new requirement for this server.
|
||||||
RUN playwright install chromium-headless-shell
|
ENV PLAYWRIGHT_BROWSERS_PATH=/data/.playwright-browsers
|
||||||
|
|
||||||
# render-service/'s dependencies installed as several separate layers
|
# render-service/'s dependencies installed as several separate layers
|
||||||
# rather than one `npm install` covering all of them -- a from-scratch
|
# 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
|
# Then execs uvicorn as the foreground/PID 1 process so it receives
|
||||||
# Docker's stop signal directly.
|
# 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
|
# Wrapped in a restart loop, not a bare `node ... &`: a bare background
|
||||||
# process that crashes stays dead for good, with nothing to bring it
|
# process that crashes stays dead for good, with nothing to bring it
|
||||||
# back -- turning any single render crash (a not-yet-found jsdom/
|
# back -- turning any single render crash (a not-yet-found jsdom/
|
||||||
|
|||||||
Reference in New Issue
Block a user