What this prompt does
This prompt makes the AI a senior platform engineer that writes a production multi-stage Dockerfile for a Node.js app that is small, secure, and fast to build. You set the [node_version], the [package_manager], and the [base_image] you prefer for runtime. It returns a Dockerfile with three stages (deps installing prod dependencies only, build for compiling or bundling, and a lean runtime that copies just what is needed), BuildKit cache mounts for your package manager, a non-root user with no secrets baked into layers, a HEALTHCHECK with correct signal handling and an explicit EXPOSE, plus a matching .dockerignore and the build and run commands.
The structure works because the deps, build, and runtime split is what keeps compilers and dev dependencies out of the final image, where they only add weight and attack surface. [node_version] pins the base tags so the image matches the runtime you actually deploy on. [package_manager] decides which lockfile and cache-mount syntax the deps stage uses, so rebuilds genuinely hit the cache instead of reinstalling from scratch every push. [base_image] is the biggest lever on final size and attack surface; a distroless or alpine runtime ships far less than a full Node image. The non-root user and minimal base together harden anything you put in front of users, which is why the prompt treats both as non-negotiable.
When to use it
- You want a small, secure Node image instead of a half-gigabyte one running as root.
- You are containerising a Node app for a cloud deploy.
- Your rebuilds are slow because the deps layer isn't cached.
- You need a non-root runtime and a minimal base for production.
- You want a HEALTHCHECK and correct signal handling baked in.
- You need a matching .dockerignore so build context stays lean.
Example output
You get the full multi-stage Dockerfile with deps, build, and runtime stages, BuildKit cache mounts for your package manager, a non-root user with no secrets baked into layers, a HEALTHCHECK, correct signal handling, and an explicit EXPOSE line, plus a matching .dockerignore, the docker build and run commands, and a note on image size before and after. Lines that aren't obvious are explained inline, so it reads as a ready-to-use file you can commit rather than a tutorial you still have to assemble.
Pro tips
- Set
[node_version]to your exact LTS so the base tags match your runtime. - Match
[package_manager]precisely; it drives the lockfile and cache-mount syntax. - Use
[base_image]to trade size against debuggability; distroless is smallest, alpine is easier to inspect. - Keep the non-root user and minimal base; both are non-negotiable for user-facing services.
- Enable BuildKit so the cache mounts actually speed up rebuilds.
- Verify the .dockerignore excludes node_modules and build artifacts so context stays small.