commit eb494b034e55ea07d47a490d1427b27d3b259f4c
parent 04dab989c7bb88216795073918d8bcb3fea0377f
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Tue, 6 Oct 2026 09:23:01 -0400
docker: the image runs Node 22 everywhere — the pinned wrangler's engines floor; one major for the build stage and every runtime
NODE_IMAGE and RUNTIME_IMAGE node:22-bookworm-slim (glibc 2.36, unchanged), the
Vulkan overlay node:22-trixie-slim, runtime-cuda NODE_MAJOR=22 on ubuntu 24.04.
Two drift tests: one Node major across all four (the native modules are built
once, against the build stage's ABI), and that major >= wrangler's engines floor
(skipped where wrangler is not installed).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
3 files changed, 62 insertions(+), 7 deletions(-)
diff --git a/Dockerfile b/Dockerfile
@@ -39,10 +39,18 @@
# bookworm is 2.36, trixie 2.41, ubuntu 24.04 2.39 — so building on bookworm and
# running on any of them is safe, and moving NODE_IMAGE to trixie would silently
# break the CUDA target. If you bump one of these, check that direction first.
-ARG NODE_IMAGE=node:20-bookworm-slim
+#
+# NODE'S MAJOR IS THE SECOND RULE, and it must be the same everywhere: the
+# native modules are compiled against the build stage's Node ABI, so every
+# runtime (NODE_IMAGE, RUNTIME_IMAGE here and in docker-compose.vulkan.yml,
+# NODE_MAJOR in runtime-cuda) carries the same major. 22, not 20: the wrangler
+# pinned in common/package.json refuses to start on anything older (its
+# engines floor), and every deploy runs it from this image.
+# common/publish/buildImage.test.ts holds all four to one major and that floor.
+ARG NODE_IMAGE=node:22-bookworm-slim
# The runtime base, overridable per target: docker-compose.vulkan.yml builds with
# trixie because the Vulkan stack needs it (see the parakeet stage below).
-ARG RUNTIME_IMAGE=node:20-bookworm-slim
+ARG RUNTIME_IMAGE=node:22-bookworm-slim
# ubuntu24.04, not 22.04: 22.04 is glibc 2.35, OLDER than the bookworm the
# workspace is built on, and the native modules would not load.
ARG CUDA_DEVEL_IMAGE=nvidia/cuda:12.6.3-devel-ubuntu24.04
@@ -456,7 +464,7 @@ ENV ARCHILYZER_COMMIT=${ARCHILYZER_COMMIT} \
# ---------------------------------------------------------------------------
FROM ${CUDA_RUNTIME_IMAGE} AS runtime-cuda
-ARG NODE_MAJOR=20
+ARG NODE_MAJOR=22
# The same python + pipx + git-filter-repo as runtime-base (read its comments).
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
diff --git a/common/publish/buildImage.test.ts b/common/publish/buildImage.test.ts
@@ -126,3 +126,50 @@ test("every runtime target names its own yt-dlp and links the from-source wrappe
assert.equal(links.length, 2);
assert.ok(existsSync(path.join(REPO, "docker", "yt-dlp-from-source.sh")));
});
+
+// Node's major, everywhere the image is built or run: the build stage
+// (NODE_IMAGE), the default runtime (RUNTIME_IMAGE), the Vulkan overlay's
+// runtime and runtime-cuda's nodesource major. The native modules are compiled
+// once against the build stage's ABI, so all of them must agree.
+function imageNodeMajors(): Record<string, number> {
+ const dockerfile = readFileSync(path.join(REPO, "Dockerfile"), "utf8");
+ const vulkan = readFileSync(path.join(REPO, "docker-compose.vulkan.yml"), "utf8");
+ const one = (re: RegExp, text: string, what: string) => {
+ const m = re.exec(text);
+ assert.ok(m, `${what} not found`);
+ return Number(m[1]);
+ };
+ const out: Record<string, number> = {
+ NODE_IMAGE: one(/^ARG NODE_IMAGE=node:(\d+)-/m, dockerfile, "ARG NODE_IMAGE=node:<major>-…"),
+ RUNTIME_IMAGE: one(/^ARG RUNTIME_IMAGE=node:(\d+)-/m, dockerfile, "ARG RUNTIME_IMAGE=node:<major>-…"),
+ NODE_MAJOR: one(/^ARG NODE_MAJOR=(\d+)$/m, dockerfile, "ARG NODE_MAJOR=<major> (runtime-cuda)"),
+ };
+ const vk = [...vulkan.matchAll(/RUNTIME_IMAGE: node:(\d+)-/g)].map((m) => Number(m[1]));
+ assert.ok(vk.length > 0, "docker-compose.vulkan.yml names a RUNTIME_IMAGE");
+ vk.forEach((v, i) => (out[`vulkan RUNTIME_IMAGE #${i + 1}`] = v));
+ return out;
+}
+
+test("every image target runs the Node major the build stage compiled the native modules for", () => {
+ const majors = imageNodeMajors();
+ assert.equal(new Set(Object.values(majors)).size, 1, `one Node major everywhere, found ${JSON.stringify(majors)}`);
+});
+
+// Every deploy runs the wrangler pinned in common's devDependencies from this
+// image, and wrangler refuses to start below its engines floor (4.x: >=22).
+// Skipped where wrangler is not installed.
+test("the image's Node major meets the pinned wrangler's engines floor", (t) => {
+ const pkg = path.join(REPO, "common", "node_modules", "wrangler", "package.json");
+ if (!existsSync(pkg)) {
+ t.skip("wrangler is not installed in common/node_modules");
+ return;
+ }
+ const engines = (JSON.parse(readFileSync(pkg, "utf8")) as { engines?: { node?: string } }).engines?.node ?? "";
+ const floor = /(\d+)/.exec(engines);
+ assert.ok(floor, `wrangler's engines.node (${JSON.stringify(engines)}) names a major`);
+ const major = imageNodeMajors().NODE_IMAGE;
+ assert.ok(
+ major >= Number(floor[1]),
+ `the image runs Node ${major}, and wrangler needs ${engines} — every deploy from the container would exit 1`,
+ );
+});
diff --git a/docker-compose.vulkan.yml b/docker-compose.vulkan.yml
@@ -38,7 +38,7 @@ services:
# The Vulkan stack needs a newer Debian than the default image runs on;
# the Dockerfile explains why, and why the workspace is still BUILT on
# the older one.
- RUNTIME_IMAGE: node:20-trixie-slim
+ RUNTIME_IMAGE: node:22-trixie-slim
image: archilyzer:${ARCHILYZER_TAG:-local}-vulkan
devices:
# The render node. This is the whole GPU passthrough — no toolkit, no
@@ -59,17 +59,17 @@ services:
build:
target: runtime-vulkan
args:
- RUNTIME_IMAGE: node:20-trixie-slim
+ RUNTIME_IMAGE: node:22-trixie-slim
image: archilyzer:${ARCHILYZER_TAG:-local}-vulkan
homepage:
build:
target: runtime-vulkan
args:
- RUNTIME_IMAGE: node:20-trixie-slim
+ RUNTIME_IMAGE: node:22-trixie-slim
image: archilyzer:${ARCHILYZER_TAG:-local}-vulkan
umtool:
build:
target: runtime-vulkan
args:
- RUNTIME_IMAGE: node:20-trixie-slim
+ RUNTIME_IMAGE: node:22-trixie-slim
image: archilyzer:${ARCHILYZER_TAG:-local}-vulkan