Repository navigation
Split the Docker build into build, deps, and runtime stages - #2422
Merged
Merged
Conversation
kmcginnes
added a commit
that referenced
this pull request
Oct 18, 2026
## Summary The Dockerfile pinned Node.js a second time in `ENV NODE_VERSION`, downloaded it with `curl | tar` and no checksum, and installed pnpm through a pinned Corepack. The build and deps stages now run in the official Vite+ image. It installs the Node.js in `.node-version` and the pnpm in `packageManager`, verifies both, and the runtime stays on the same Amazon Linux 2023 snapshot. ```diff -FROM amazonlinux:2023.… AS os -ENV NODE_VERSION=24.21.0 -FROM os AS toolchain # curl nodejs.org | tar, npm i -g corepack@0.36.0 +FROM ghcr.io/voidzero-dev/vite-plus:1.1.0@sha256:… AS toolchain FROM toolchain AS build vp install, vp run build, export node + LICENSE FROM toolchain AS deps vp install --prod -FROM os AS runtime +FROM amazonlinux:2023.… AS runtime ``` `.node-version` is now the only Node.js pin the image uses. `test_build_docker.yml` checks that the image's `node --version` matches it. `docs/development.md` and the Dependabot comments drop the Corepack and `NODE_VERSION` notes. ## Evidence **Before:** the image's Node.js came from `ENV NODE_VERSION`, with no signature or checksum check, and pnpm came from Corepack 0.36.0. **After:** the image builds with `Done in 15.7s using pnpm v12.8.1`. The new CI step reports `✓ node v24.21.0`, which matches `.node-version`. Compared with an image built from current `main`: - **Contents:** every file under `/graph-explorer` and `/usr/local` is byte-identical, with the same owners and modes. The only exceptions are `Dockerfile` and pnpm's install metadata. `/usr/local/bin/node` has the same SHA-256, so Vite+ fetched the same official build. - **Config:** `ExposedPorts`, `Entrypoint`, `WorkingDir`, `User`, `PATH` and `HOME` are unchanged. `NODE_VERSION` is gone from the image environment. - **Size:** 875 MB, the same as before. - **Trivy:** no HIGH or CRITICAL findings. **Verified live:** I ran both images through every documented deployment path and compared the results: - **Startup:** both answer `/status` over HTTP on 80, in notebook mode on 9250, and over HTTPS on 443. - **Config:** a mounted `config.json`, read-write and read-only, gives identical `.env`, `defaultConnection.json` and `/defaultConnection`. - **Config folder:** a `CONFIGURATION_FOLDER_PATH` folder with a user `.env` ends up with identical contents. - **Certificates:** bind-mounted user certificates are served the same way, and a restart keeps the same certificate. - **Upgrade from 3.3.0:** a config folder and a `cert-info` named volume written by the published 3.3.0 image work unchanged on the new image. The volume serves the same certificate fingerprint. - **Stop:** `docker stop` takes 0.13s and exits 0. ## Merge Danger **Door:** two-way **Impact:** Docker image The shipped image has the same contents and behavior. One environment variable disappears: `NODE_VERSION` is no longer set inside the container. Nothing in this repo reads it, and it was only ever set to report the build's Node.js version. Builds now pull `ghcr.io/voidzero-dev/vite-plus`, pinned by digest, in addition to the Amazon Linux image. ## Related - Related to #2305 - Related to #2422
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The image was built in one stage. It installed everything, built, deleted
node_modules, reinstalled production dependencies in place, then stripped npm, pnpm and corepack back out. Splitting it into stages gives the same image without the cleanup pass, and production dependencies get a layer that is reused until a manifest changes. Both build stages and the runtime stay on the same pinned Amazon Linux 2023 snapshot.The runtime never gets npm, pnpm or corepack, so nothing has to be uninstalled.
test_build_docker.ymlnow also starts the image in notebook mode on 9250 and over HTTPS on 443, in addition to the plain HTTP run on 80.Evidence
Old and new images were each built from a clean checkout of
mainand compared:ExposedPorts,Entrypoint,WorkingDir,User,PATH,NODE_VERSIONandHOMEare identical.VP_GIT_HOOKSnow lives only in the build stage, since nothing runs git at runtime./graph-explorerhas the same 41,681node_modulesentries. The app tree matches too, except for 4 npm log files the old image carried in.npm/./statusover HTTP on 80, in notebook mode on 9250, and over HTTPS on 443.CONFIGURATION_FOLDER_PATHfolder with a user.envstarts and serves the same/defaultConnection. Acert-infonamed volume serves the same certificate, matched by SHA-256 fingerprint, withoutHOST.mainimage, a mountedconfig.json(read-write and read-only) produces identical.env,defaultConnection.jsonand/defaultConnection. A config folder ends up with identical contents, and bind-mounted user certificates are served the same way.node --versionisv24.21.0,opensslis present, and npm, pnpm, corepack, python3, yum and dnf are absent.Merge Danger
Door: two-way
Impact: Docker image
The published image has the same contents and entrypoint, so users and the notebook setup see no change. A failure would show up at container start, which the 3
/statusruns check.Related