Choosing a Base Image

The FROM line decides most of an image's size, its security exposure and how pleasant it is to debug. For a Node.js 2,131 service like BookNest there are five realistic candidates, all pulled and measured on this host with docker image ls:

Node.js base images compared (sizes are compressed download sizes, September 2026)
Image Download Base, C library Shell and package manager
node:24 426 MB Debian 319 , glibc Yes; compilers and build tools too
node:24-slim 83 MB Debian 12, glibc Yes (apt), no build tools
node:24-alpine 62 MB Alpine 13,255 , musl Yes (apk)
gcr.io/distroless/nodejs24-debian13 55 MB Debian 13, glibc None; root by default, :nonroot tag
cgr.dev/chainguard/node 69 MB Wolfi 1,291 , glibc BusyBox 65,982 shell; free tier offers latest only

The full node:24 image carries compilers only a build stage needs. node:24-alpine is the smallest with a shell, but musl occasionally breaks native add-ons. Distroless 23,100 images from Google (GoogleContainerTools/distroless (https://github.com/GoogleContainerTools/distroless 23,100 )) contain the runtime and nothing else: no shell for an attacker to use, and nothing for a vulnerability scanner to flag, but also nothing for you to debug with. Chainguard 179,813 images are rebuilt daily for a near-zero CVE count, and Docker 514 's own Hardened Images (dhi.io) aim at the same goal but require a Docker login even for the free ones (an anonymous pull here failed with 401 Unauthorized). Chainguard's free latest tag already runs Node.js 26.10.0 (node -e 'console.log(process.version)'), a reminder that "latest" means "whatever was built last".

BookNest Dockerfile's Dockerfile for BookNest's API uses node:24-slim: glibc, a shell for debugging, 83 MB, and the same Debian family as postgres:18.