commit c6f8a5ace100bfe0abf1c1c03796d82f53f11f5c
parent 2bc6b88e589fa2ead48d87766567b503356a7ea1
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 28 Sep 2026 13:13:38 -0400
docker: Dockerfile.build.dockerignore — the build image's context is an allow-list, about 7 MB from any checkout
BuildKit reads <Dockerfile>.dockerignore beside the Dockerfile in place of the
shared .dockerignore, which the root Dockerfile and Dockerfile.test keep. The
image now bakes the root manifests, common/, export/ (its public/ only the
tracked .svg assets) and docker/build-site.sh: 807 files, 7.4 MB from the
primary checkout as from a worktree (the rules emulated over both and checked
file-for-file against the built image). Under the shared file the primary sent
export/public's generated data (subs/ alone 1.8 GB), .diarize/, umtool's data
and the rest — the live image's COPY layer was 3.23 GB, and its chmod layer
3.18 GB more; they are now 7.1 MB and 1.0 MB, so COPY --chmod is not needed.
Dockerfile.build's comments say what the context is, why the pnpm 11
verify-deps env stays (a builder that reads only the shared .dockerignore bakes
all seven packages), and why export/ is writable (build-site.sh links
export/public to the composed /site/public).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 56 insertions(+), 9 deletions(-)
diff --git a/Dockerfile.build b/Dockerfile.build
@@ -45,22 +45,28 @@ RUN pnpm install --frozen-lockfile
# Only common and export (and the root) are installed — all the export build
# needs. Before every `pnpm exec` / `pnpm run`, pnpm 11 checks that the WHOLE
-# workspace is installed and runs `pnpm install` when it is not; after `COPY . .`
-# below it never is, and that install fails as the non-root runtime uid
-# (EACCES on /repo). The deps are frozen here, so the check is off. So is the
-# update notice, which every site's log would otherwise print.
+# workspace is installed and runs `pnpm install` when it is not, which fails as
+# the non-root runtime uid (EACCES on /repo). Dockerfile.build.dockerignore
+# admits no other workspace package, so today the check passes; it is off anyway,
+# because a builder that reads only the shared .dockerignore bakes all seven and
+# the first `pnpm exec` dies. The deps are frozen here. The update notice is off
+# too: every site's log would print it.
ENV pnpm_config_verify_deps_before_run=false \
pnpm_config_update_notifier=false
-# Bake source last so a code change only re-runs from here.
+# Bake source last so a code change only re-runs from here. The context is
+# Dockerfile.build.dockerignore's allow-list — root manifests, common/, export/
+# (its public/ only the tracked .svg assets) and docker/build-site.sh: about
+# 7 MB from any checkout, and never a corpus byte.
COPY . .
# Containers run with `-u <host-uid>` (so /site outputs are host-owned, not root).
# Next writes a couple of fixed-location files into the export package dir
-# (next-env.d.ts, tsconfig.tsbuildinfo) and the entrypoint symlinks .next/out from
-# there — so that one dir must be writable by an arbitrary runtime uid. Every
-# container is ephemeral (`docker run --rm`) and writes nothing back but its /site
-# mount, so widening it here is harmless.
+# (next-env.d.ts, .next/) and the entrypoint replaces export/public with a link
+# to the composed /site/public — so export/ must be writable by an arbitrary
+# runtime uid. Every container is ephemeral (`docker run --rm`) and writes nothing
+# back but its /site mount, so widening it here is harmless. The layer repeats
+# export/'s few MB of source, not the image.
RUN chmod -R a+rwX /repo/export
ENTRYPOINT ["bash", "docker/build-site.sh"]
diff --git a/Dockerfile.build.dockerignore b/Dockerfile.build.dockerignore
@@ -0,0 +1,41 @@
+# The build context of Dockerfile.build ONLY. BuildKit reads <Dockerfile>.dockerignore
+# beside the Dockerfile in place of the shared .dockerignore, which the root Dockerfile
+# and Dockerfile.test keep using unchanged.
+#
+# An allow-list: everything is out, then only what one site's export build reads
+# (docker/build-site.sh → `archilyzer build site <id> --nodata` → compose + next
+# build) is let back in. The corpus, the index, the staging and the settings are
+# MOUNTED at run time (common/publish/build.ts, runDockerBuildOne) and never baked.
+#
+# What this keeps out, measured on the primary checkout: export/public's generated
+# data (subs/ alone is 1.8 GB — and a site's `next build` would publish whatever sat
+# there), .diarize/ (1.3 GB), umtool's data, editor/, homepage/, mcp/, plans/.
+*
+!package.json
+!pnpm-lock.yaml
+!pnpm-workspace.yaml
+!tsconfig.base.json
+!common
+!export
+!docker/build-site.sh
+
+# Inside common/ and export/: nothing generated, cached, local or secret. No
+# tracked file in either starts with a dot.
+common/.*
+export/.*
+**/node_modules
+**/.next
+**/out
+**/*.tsbuildinfo
+**/next-env.d.ts
+**/.env*
+**/*.pem
+export/test-*
+export/playwright-report
+export/blob-report
+
+# export/public holds generated data beside the repo's tracked assets (all .svg).
+# Only the assets are baked: build-site.sh copies them into the site's composed
+# public/, which is what `next build` publishes.
+export/public/*
+!export/public/*.svg