💻 Coding
Multi-Stage Dockerfile from a Service Spec (Version-Locked Base Image)
Write a multi-stage Dockerfile from a service spec with a pinned base image digest or tag. No floating latest, no invented ports.
0Reviews
Prompt
Act as a platform engineer writing a multi-stage Dockerfile from a service spec. You lock the base image to the tag or digest in Inputs. You do not use :latest. You do not invent ports, build args, secrets, or OS packages. Target Docker BuildKit syntax only if Inputs name it. You work only from Inputs. Do not invent stats, citations, quotes, URLs, names, IDs, or records that are not in Inputs. Inputs: - Service name, language, and version: [Service] - Base image with exact tag or digest: [Base] - Runtime image with exact tag or digest: [Runtime] - Build commands I actually run: [Build] - Runtime command and working directory: [Cmd] - Ports the process listens on: [Ports or NONE] - Files to copy (include/exclude): [Files] - User the process must run as: [User or NONE] - BuildKit features I allow (or NONE): [Buildkit] - Words I must not use: [Banned] Generate: 1. Version lock: quote Base and Runtime. Refuse :latest and any tag not in Inputs. If digest is missing, say tag-only pin and do not invent a sha256. 2. Stage map: builder and runtime. Name stages. List COPY --from sources from Files only. 3. Dockerfile: syntax line only if Buildkit names a syntax image. FROM pins exact. RUN only Build commands. No apt packages unless Build names them. 4. USER, WORKDIR, EXPOSE, CMD/ENTRYPOINT from User, Cmd, Ports. If Ports is NONE, omit EXPOSE rather than guessing 8080. 5. .dockerignore sketch from Files exclude list only. 6. Build and run commands the operator can paste, using the pins. No invented registry. 7. Gaps: secrets, healthcheck, non-root user, digest, if missing. 8. Compliance pass: quote Banned words, :latest, invented EXPOSE, invented apt packages. Cut them. Constraints: - Multi-stage Dockerfile. Do not emit a Compose file unless Inputs include one. - Never float :latest. Never invent a digest. - Do not add curl, bash, or debug shells unless Build names them. - If User is NONE, do not invent a uid; note that the image user is unspecified. - No emojis.
Instructions
Replace every [bracket] with your details before running. Works on ChatGPT, Claude, and Gemini.
Examples
Example Input
Service: pay-api, Go 1.23.6, module github.com/northwind/pay-api Base: golang:1.23.6-bookworm (tag only, no digest pasted) Runtime: gcr.io/distroless/static-debian12:nonroot (tag only) Build: CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o /out/pay-api ./cmd/pay-api Cmd: WORKDIR /app; ENTRYPOINT [/app/pay-api]; no shell Ports: 8443/tcp. Not 8080. Files: copy go.mod go.sum and cmd/ internal/ pkg/; exclude testdata/ *.md .git User: distroless nonroot (uid not pasted) Buildkit: syntax docker/dockerfile:1.7.0; no secret mounts named Banned: latest, alpine debug, curl in prod, EXPOSE 8080
Example Output
1. Version lock. Builder golang:1.23.6-bookworm. Runtime gcr.io/distroless/static-debian12:nonroot. Tag-only pins. Do not invent sha256. Refuse :latest, alpine, golang:1.24. 2. Stages. builder: compile /out/pay-api. runtime: copy binary only. COPY --from=builder /out/pay-api /app/pay-api. No testdata. 3. Dockerfile. # syntax=docker/dockerfile:1.7.0. FROM golang:1.23.6-bookworm AS builder. WORKDIR /src. COPY go.mod go.sum ./ then go mod download. COPY cmd/ internal/ pkg/. RUN CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o /out/pay-api ./cmd/pay-api. FROM gcr.io/distroless/static-debian12:nonroot. COPY --from=builder /out/pay-api /app/pay-api. WORKDIR /app. EXPOSE 8443. ENTRYPOINT ["/app/pay-api"]. No apt-get. No curl. 4. USER: image is distroless nonroot; uid NOT IN INPUTS so do not write USER 65532 unless confirmed. Ports: 8443 only. 5. .dockerignore. testdata/ *.md .git. Do not ignore go.mod. 6. Build. docker build -t pay-api:local . with Dockerfile 1.7.0 syntax. Run. docker run --rm -p 8443:8443 pay-api:local. Registry: NOT IN INPUTS. 7. Gaps. Digests, uid number, healthcheck, CA bundle, GOPROXY, secret mounts. 8. Compliance. Cut: latest, alpine debug, curl in prod, EXPOSE 8080. No Compose. Missing-data policy: if a field was blank, write NOT IN INPUTS rather than guessing. Lock any tool version named in Inputs; if unnamed, write unknown. No invented testimonials, star ratings, or press logos. If legal, clinical, insurance, HR, education-plan, or veterinary content appears, add a one-line not-advice and de-identify banner. Quote banned-word hits and cut them. End with a gaps list of five bullets the user still owes you. Character and byte caps in the job are hard; print counts when relevant. Refuse to backfill DOIs, exam dumps, PHI, PII, or compensation promises not in Inputs.