Generate a Production-Ready Dockerfile and Explain Each Line
Generate a hardened, multi-stage Dockerfile with line-by-line comments and matching .dockerignore.
This prompt produces a hardened, multi-stage Dockerfile for your stack with a comment on every line explaining why it's there, plus a matching .dockerignore and a note on runtime arguments. It's for developers who want a production-grade image — small, non-root, no leaked secrets — and who want to understand the decisions rather than copy-paste a black box. The hard constraints (multi-stage, slim base, dependency-layer caching, no secrets in the image) encode container best practices that are easy to get wrong, and the per-line comments turn the output into a learning artifact you can defend in code review.
Write a production-grade Dockerfile for a [LANGUAGE/FRAMEWORK] application. Constraints: multi-stage build, non-root user, slim base image, layer caching for dependencies, no secrets in image. For each line, add a brief comment explaining WHY it's there. Also include a `.dockerignore` and a one-paragraph note on what runtime args to pass and why.
What you can expect back
# ---- Build stage ---- FROM node:20-slim AS build # slim base: smaller, fewer CVEs than full image WORKDIR /app COPY package*.json ./ # copy manifests first so deps cache across code changes RUN npm ci # ci = reproducible install from lockfile COPY . . # copy source after deps for better layer caching RUN npm run build # produce build artifacts in this throwaway stage # ---- Runtime stage ---- FROM node:20-slim AS runtime WORKDIR /app ENV NODE_ENV=production # disables dev behavior, trims dependencies COPY --from=build /app/node_modules ./node_modules # bring only built artifacts COPY --from=build /app/dist ./dist # no source/build tools in final image USER node # run as non-root to limit blast radius EXPOSE 3000 # document the port (does not publish it) CMD ["node", "dist/server.js"] # exec form so signals reach the process .dockerignore: node_modules npm-debug.log .git .env Dockerfile Runtime note: Pass secrets at runtime, never bake them in: docker run -e DATABASE_URL=... -p 3000:3000 myapp. Keeping .env out of the image (via .dockerignore) and injecting env vars at run time means the image stays generic and credentials never end up in a layer.
Illustrative example — your results will vary by tool and inputs.
Get sharper results
- 01Name the exact runtime version (Node 20, Python 3.12) so the base image tag is pinned and your builds stay reproducible instead of silently drifting.
- 02Ask it to pin the base image by digest as well as tag if you need fully deterministic, supply-chain-hardened builds.
- 03If your app needs build-time native dependencies, mention them so the build stage installs the right system packages and the runtime stage stays slim.
- 04Have it add a HEALTHCHECK instruction tuned to your app's health endpoint so orchestrators can detect a hung container.
- 05Request the equivalent docker build and docker run commands alongside the Dockerfile so you can test the multi-stage build end to end immediately.
Adapt it for your case
Ask it to use a distroless or scratch base for the runtime stage to shrink the image and attack surface even further.
Add 'also write a docker-compose.yml wiring this service to a Postgres container with a named volume' for local development.
Specify a compiled language and ask for a scratch-based final image containing only the static binary.
Common questions
Why a multi-stage build?
It lets you compile in a fat build stage with all the tooling, then copy only the finished artifacts into a clean runtime image, so build tools and source never ship to production.
How does this keep secrets out of the image?
Secrets are injected at runtime as environment variables (or via a secrets manager) and .env is excluded by .dockerignore, so credentials never get baked into a cached layer that could be extracted.
Will this image actually be small?
The slim base and multi-stage copy keep it lean, but final size depends on your dependencies; ask for a distroless or scratch variant if you need to minimize it further.
You may also need
Build and Explain a Regular Expression
Get a working regex with a plain-English breakdown and a set of passing/failing test cases.
Port a code snippet to another language idiomatically
Translates a snippet into idiomatic code in a target language and flags cross-language correctness pitfalls.
Diagnose and rewrite a slow SQL query using its plan
Reads a query plan to explain why a SQL statement is slow, then rewrites it and recommends indexes.
Brainstorm edge-case test scenarios before you write tests
Enumerates grouped edge-case and adversarial test scenarios for a feature so nothing gets shipped untested.