DevOps & Cloud

Verified against ChatGPT · 2026-08-08

Turn a working Dockerfile into a multi-stage build that doesn't ship your build toolchain to production

Rewrites a single-stage Dockerfile into a hardened multi-stage build with a minimal runtime image, a non-root user, and an explicit rationale for every layer decision, so image size and attack surface actually get reviewed instead of copy-pasted from a tutorial.

ChatGPT (GPT-5.1)5 fillable variables

The prompt

Ready to copy — highlighted parts are example details you can swap.

You are a senior software engineer rewriting a Dockerfile for production use, not for a quick local demo. I'll give you the current Dockerfile (or a description of the app if none exists yet) and the runtime constraints, and you produce a multi-stage version plus a short review of what you changed and why.

CURRENT DOCKERFILE OR APP DESCRIPTION
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/server.js"]

RUNTIME (language/framework, version)
Node.js 20 LTS, Express API, no native addons

BASE IMAGE CONSTRAINT
Must come from our internal Artifactory mirror of official Docker Hub images; Alpine variants preferred for size but must pass Trivy scan with zero criticals

SECRETS OR BUILD-TIME ARGS IN USE
A read-only npm token for our private @acme scope, currently passed as a plain ARG (this is the bug we're fixing)

DEPLOYMENT TARGET
AWS ECS Fargate, tasks get SIGTERM on deploy with a 30-second grace period

RULES FOR THE REWRITE
Separate the build stage from the runtime stage explicitly — compilers, dev dependencies, and build tools must never appear in the final layer. Pin the base image to a specific digest or exact version tag, never `latest`, and justify the choice against the base image constraint given. Run the final container as a non-root user created in the Dockerfile, not root with a comment saying to fix it later. If build-time secrets are involved, use BuildKit secret mounts or multi-stage copy tricks to keep them out of any layer's history — never bake a credential into an `ENV` or `ARG` that persists in the image. Order instructions so that the least-frequently-changing layers (dependency installation) come before the most-frequently-changing ones (application source) to maximize build cache hits. Add a `HEALTHCHECK` instruction appropriate to the deployment target, and explain why you picked its interval and retry values rather than using defaults with no reasoning.

WHAT NOT TO DO
Do not add unrelated optimizations the user didn't ask about (multi-arch builds, distroless conversion) without flagging them as a separate optional suggestion at the end, clearly separated from the required rewrite. Do not silently drop a system dependency the original Dockerfile installed without confirming it's actually unused by the runtime stack given.

OUTPUT FORMAT
1. The full rewritten Dockerfile in a single code block.
2. A short table: layer/instruction, what changed, why.
3. One paragraph on the resulting image size trade-off and any caching implications.
4. A separate 'optional, not applied' list for anything you noticed but didn't change unprompted.

Customize

Optional — swap in your own details for the highlighted parts above.

Why this works

The rewrite works because it forces the model to reason about the two Dockerfiles that actually matter — the one that builds and the one that ships — as separate artifacts with separate concerns, which is exactly the distinction most tutorial-derived Dockerfiles skip; a single-stage build has no structural way to keep a compiler or dev-dependency tree out of the final image, so asking generically to 'optimize' a Dockerfile without naming the multi-stage requirement tends to produce cosmetic changes like combining RUN lines rather than the actual attack-surface reduction. Pinning the base image to a digest instead of a tag matters mechanically because `latest` and even semver tags are mutable pointers — a rebuild six months later can silently pull a different image with different CVEs, which defeats any scanning done at review time; naming this explicitly stops GPT-5.1 from defaulting to the more common but weaker `FROM node:20-alpine` pattern it has seen far more often in training data than the pinned-digest form. The non-root user requirement addresses a specific, checkable failure mode: a container running as root inside is one kernel-level container-escape bug away from root on the host, and this is exactly the kind of finding that gets deferred as 'we'll fix it later' unless the Dockerfile is rejected for missing it up front. The layer-ordering instruction is a direct lever on build cache economics — Docker invalidates every layer after the first changed one, so copying source before installing dependencies means every single build reinstalls all dependencies from scratch, which compounds into real CI minutes and cost at scale; stating the ordering rule explicitly prevents the model from defaulting to whatever order the original Dockerfile happened to use.

What you get back

```dockerfile # ---- build stage ---- FROM node:20.11.1-bookworm-slim@sha256:abcd... AS build WORKDIR /app COPY package*.json ./ RUN --mount=type=secret,id=npm_token \ NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci COPY . . RUN npm run build # ---- runtime stage ---- FROM node:20.11.1-bookworm-slim@sha256:abcd... AS runtime RUN useradd --uid 1001 --create-home appuser WORKDIR /app COPY --from=build --chown=appuser:appuser /app/dist ./dist COPY --from=build --chown=appuser:appuser /app/node_modules ./node_modules USER appuser HEALTHCHECK --interval=15s --timeout=3s --retries=3 CMD node healthcheck.js CMD ["node", "dist/server.js"] ``` Layer table follows, noting the npm token now never touches a committed layer and the image dropped from 1.1GB to roughly 240MB.

Verified against

ChatGPT GPT-5.1 · 2026-08-08

Changelog

  • 2026-08-08 Initial publish, verified against ChatGPT GPT-5.1.

Need this built into your business?

If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.

EXPLORE CUSTOM SOFTWARE
Design a CI workflow that fails fast, isolates flaky tests, and doesn't punish contributors for a broken shared runnerBuilds a CI pipeline configuration (jobs, stages, caching, retry policy) for a real repo's constraints, plus an explicit flaky-test quarantine strategy, instead of a generic lint-test-build template that ignores how the team's tests actually behave today.ChatGPT (GPT-5.1)2026-08-10Write a Kubernetes manifest that won't get OOMKilled at 2am because nobody set real resource limitsGenerates a Deployment/Service manifest set with resource requests and limits derived from actual observed usage, a rollout strategy suited to the workload, and readiness/liveness probes that won't cause a self-inflicted outage during deploy.ChatGPT (GPT-5.1)2026-08-12Get a security review of an infrastructure change before it merges, not a generic OWASP checklistReviews a specific infrastructure or config change (IaC diff, new service, permission grant) for concrete security issues tied to what actually changed, ranked by exploitability, instead of a boilerplate security checklist that doesn't engage with the diff.ChatGPT (GPT-5.1)2026-08-13Plan a major dependency upgrade so breaking changes get caught before your users find themTurns a scary major-version dependency bump into a scoped upgrade plan — breaking-change inventory, migration order, and a rollback trigger — based on the actual changelog and codebase usage instead of a blind bump-and-hope.ChatGPT (GPT-5.1)2026-08-14
All DevOps & Cloud prompts

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY