Skip to content

Build the image in stages and run compiled JavaScript - #92

Merged
adamshiervani merged 1 commit into
devfrom
dockerfile-multi-stage
Nov 6, 2026
Merged

adamshiervani merged 1 commit into
devfrom
dockerfile-multi-stage

Conversation

@adamshiervani

@adamshiervani adamshiervani commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor
  • Compile with tsc in a build stage. Type errors now fail the build, not container startup.
  • Runtime stage: production dependencies only, USER node, tini as init, HEALTHCHECK on /healthz. Image is 524 MB (was 828 MB).
  • Move ts-node, typescript, @tsconfig/node22 and @types/* to devDependencies. start runs dist/index.js.
  • Exclude .env.* from the build context.
  • CI runs on Node.js 22.23.4 to match engines.

Migrations stay manual.

Tested: image build, prisma migrate deploy as node, /healthz, Docker health healthy, docker stop in 254 ms, npm test (106 passed).


Note

Medium Risk
Changes production container startup, process supervision, and dependency/runtime footprint; verify orchestration still passes env/PORT and health probes behave as expected.

Overview
Runtime now ships compiled JS, not ts-node. npm start runs node dist/index.js, main points to dist/index.js, and TypeScript/ts-node tooling moves to devDependencies with engines tightened to Node >=22.23.4 <23 and a matching CI bump.

Docker image is multi-stage and slimmer. A build stage runs prisma generate, tsc, and npm prune --omit=dev; the runtime stage copies only prod node_modules and dist, runs as USER node, wraps Node with tini, and adds a /healthcheck via /healthz. .dockerignore now drops .env.* while keeping .env.example.

Risk / testing notes. Author reports image build/tests pass; ensure HEALTHCHECK aligns with any non-default PORT and that any non-Docker deploy paths also use the compiled entrypoint.

Reviewed by Cursor Bugbot for commit 0094779. Bugbot is set up for automated code reviews on this repo. Configure here.

Compile with tsc at build time, so a type error fails the build instead
of crash-looping the container. The runtime stage has production
dependencies only, runs as the node user under tini, and has a
HEALTHCHECK on /healthz.

Move ts-node, typescript, @tsconfig/node22 and @types/* to
devDependencies. Keep .env.* files out of the build context. Run CI on
Node.js 22.23.4 to match engines.
@adamshiervani
adamshiervani marked this pull request as ready for review November 6, 2026 09:39
@adamshiervani
adamshiervani merged commit 5f951af into dev Nov 6, 2026
3 checks passed
adamshiervani added a commit that referenced this pull request Nov 6, 2026
main has the Node.js 22.23.4 and Dockerfile changes as squash commits;
dev has the same changes and the multi-stage Dockerfile from #92, so
dev's files are kept.
adamshiervani added a commit that referenced this pull request Nov 6, 2026
… compiled image, e2e tests (#90)

- #88: a new SKU's first staged release reaches devices in its bucket; no compatible default is null, not 404.
- #89: new releases register at 0%, and a 0% row never displaces a rollout in progress.
- #92: multi-stage Docker image; the container runs compiled dist/index.js as node under tini, with a HEALTHCHECK.
- #93: e2e tests and npm run compare. DELETE /devices/:id without credentials answers 401; WebSocket upgrade and device disconnect errors are caught. A request that pins one part gets the other part from the rollout. Prerelease checks fall back to the newest of the 5 newest versions with a build for the SKU; the latest-file redirects answer 404 when the newest version has no file for the SKU.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant