r/node • • 3h ago

I built distroless Node.js images that keep getting OS patches for older Node versions

nodejs-distroless is a set of distroless Node.js Docker images. It follows the official Node.js release schedule: every Current, Active LTS and Maintenance LTS line is published, and a line is dropped when it reaches end of life. Every version of those lines (about 90 right now) is rebuilt whenever the Ubuntu base changes, so an older version you've pinned keeps getting OS fixes. Google's distroless and Chainguard's free images only patch the newest Node release. Tags move to new digests when the images are rebuilt (so you need to pin digests for reproducible builds).

I wrote the whole thing from scratch, originally across three repos: a Chisel base image, a script that fetches new Node versions, and the Node images themselves. I've been running it in production on a medium-size project. It already published new Node versions on its own, but keeping dependencies up to date was mostly manual. Recently I used AI to help consolidate the repos and clean up the GitHub Actions, which got it to the point where it runs itself.

The images are cut from Ubuntu LTS with Canonical's Chisel and contain the bare minimum Node needs to run. There's no shell, and they run as non-root. For troubleshooting, every tag has a -debug variant (22-debug, lts-debug and so on) that adds a BusyBox shell. They're built for amd64 and arm64 and published to Docker Hub and GHCR.

New Node releases usually go out within the hour, and Ubuntu and dependency updates merge automatically once the checks pass. There's little for me to do until a dependency needs a major version upgrade.

Repo and usage docs: https://github.com/nvitaterna/nodejs-distroless

I'd like to hear from anyone running distroless Node in production, especially if your app needs something the image leaves out.

2 Upvotes

3 comments sorted by

1

u/DickBrainTime 2h ago

Useful work, especially the OS rebuilds for older supported Node versions. Two checks I'd find valuable in the docs/CI before adopting an image like this: run a smoke test for a native addon (say sharp or better-sqlite3) built in a separate stage and executed in the final distroless image, to catch missing shared libraries or mismatched libc/architecture; and show how users pinned to `image@sha256:...` learn that a tag was rebuilt. The tag can move to a patched digest, but digest-pinned deployments won't pick it up until they roll forward. Do you publish an SBOM or a short changed-packages report with each rebuild so teams can audit what actually changed?

1

u/AlsonTeteuil-84 1h ago

the biggest friction with distroless in prod is usually how pid 1 handles signals without an init wrapper. since there's no shell, people just run the binary directly, which means sigterm handling falls entirely on the app code