build(seeder): shrink the image build context and cache the dependency layer
The seeder image build handed podman a build context full of files the Dockerfile never reads, and reinstalled the entire dependency tree on every release because the source copy came before `npm ci`. Two changes, neither of which alters what is built: - `.dockerignore` now excludes the desktop installer formats (*.AppImage, *.dmg, *.exe, *.deb, *.pkg) and the Start9 packaging output (*.s9pk plus seeder-launcher/start9/docker-images). The repo root accumulates a full set of installers on every release and none of it is referenced by the umbrel Dockerfile. - The builder stage copies package.json, package-lock.json and patches/ first, runs `npm ci`, and only then copies the sources. patches/ has to come along: postinstall runs patch-package, and without the directory the build still succeeds and quietly ships a seeder on unpatched autobase. Measured on this machine, linux/amd64, podman: build context 2.5 GB -> 1015 MB cold build 224s -> 155s rebuild after a one-line src change 224s -> 35s The rebuild figure is the real point: before, any source edit invalidated the install layer, so an incremental rebuild cost exactly as much as a cold one. Verified the output is unchanged rather than assuming it: the shipped /app payload is byte-identical across 267 of its 268 files, and the one that differs is host/brand.png, whose pixel signature is identical and whose 14 differing bytes are ImageMagick's embedded date chunks - non-deterministic on every build, before this change and after. patch-package reports autobase@7.25.1 applied in both. Image size is 365 MB either way. The amd64 image boots: worklet up, dashboard listening, /api/status 200. The arm64 leg builds too, staging linux-arm64. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VzbDH8kk3vYuQ1CzNNz39h
This commit is contained in:
co-authored by
Claude Opus 5
parent
11f6759bcd
commit
8841044750
@@ -21,6 +21,20 @@ assets/*.bundle
|
||||
*.ipa
|
||||
*.keystore
|
||||
*.jks
|
||||
# Desktop installers. These were missing, and the repo root accumulates every
|
||||
# release's artifacts - 6.4 GB of them as of 2026-07-27 - so the whole lot was
|
||||
# being tarred up and handed to podman on every seeder image build, twice (once
|
||||
# per platform), for a Dockerfile that references none of it.
|
||||
*.AppImage
|
||||
*.dmg
|
||||
*.exe
|
||||
*.deb
|
||||
*.pkg
|
||||
# Start9 packaging output: the s9pk itself plus the exported image tars it is
|
||||
# built from. Another 1.8 GB of build context the umbrel image never reads.
|
||||
*.s9pk
|
||||
*.s9pk.sha256
|
||||
seeder-launcher/start9/docker-images
|
||||
metadata
|
||||
proposals
|
||||
.github
|
||||
|
||||
@@ -19,11 +19,23 @@
|
||||
# ---- builder (always native via $BUILDPLATFORM) ----------------------------
|
||||
FROM --platform=$BUILDPLATFORM node:22-bookworm AS builder
|
||||
WORKDIR /src
|
||||
# Full repo (see .dockerignore for what's excluded — notably node_modules, which
|
||||
# we regenerate so the prebuilds match).
|
||||
COPY . .
|
||||
# Dependencies BEFORE sources, so the install layer is cached.
|
||||
#
|
||||
# This used to be `COPY . .` followed by `npm ci`, which meant ANY source change
|
||||
# invalidated the install layer and reinstalled the whole dependency tree from
|
||||
# scratch on every release — twice, once per platform. Copying just the manifests
|
||||
# first lets the layer survive until a dependency actually moves.
|
||||
#
|
||||
# patches/ must come along: postinstall runs patch-package, and without the
|
||||
# directory the autobase patch would silently not apply. That would not fail the
|
||||
# build — it would quietly ship a seeder running unpatched autobase.
|
||||
COPY package.json package-lock.json ./
|
||||
COPY patches ./patches
|
||||
# Regenerate node_modules so the worklet bundle + native prebuilds are present.
|
||||
RUN npm ci --no-audit --no-fund
|
||||
# Now the sources (see .dockerignore for what's excluded — notably node_modules,
|
||||
# which we regenerate above so the prebuilds match).
|
||||
COPY . .
|
||||
# Stage the flat payload (bare, worklet/, host/ + qrcode, package.json) for the
|
||||
# TARGET arch. TARGETARCH (amd64 | arm64) comes from the build platform; map it
|
||||
# to the bare-runtime triple. SEEDER_VERSION (passed by the image build script)
|
||||
|
||||
Reference in New Issue
Block a user