What this prompt does
This prompt rewrites a Dockerfile for size, security, and build speed — and returns a working file, not a list of tips. It casts the assistant as a senior DevOps engineer and takes four context variables: [app_language], [base_image_pref], [runtime], and the current [dockerfile]. The deliverables are a multi-stage build separating build and runtime, a minimal base image with pinned versions and no floating tags, a non-root user with a read-only filesystem where possible, BuildKit cache mounts and a COPY order tuned for layer caching, a HEALTHCHECK plus removal of unnecessary build tools, and a one-line estimate of size savings and the main attack surface removed.
The structure works because it targets the three things a careless Dockerfile gets wrong at once: it's huge (slow pulls and scaling), insecure (running as root with build tools shipped to production), and slow to rebuild (poor layer caching). The [base_image_pref] variable (distroless or alpine) drives the size and attack-surface wins, while the COPY-order requirement is the single change that makes most rebuilds near-instant by caching dependencies separately from source.
When to use it
- Any image headed to production that's grown bloated over time
- When a container still builds and runs as root
- When slow image pulls are hurting deploy and autoscale times
- When you want a smaller attack surface without rewriting the app
- When rebuilds are slow because dependencies and source share a layer
- When standardizing Dockerfiles across services to a hardened baseline
Example output
You get the full improved Dockerfile in one block: a multi-stage build, a pinned minimal base matching [base_image_pref], a non-root user, BuildKit cache mounts, a tuned COPY order, and a HEALTHCHECK, with build-only tools stripped from the final stage. Below it sits a one-line savings summary estimating the size reduction and naming the main attack surface removed. The Dockerfile is meant to drop in and build, not serve as a checklist. The multi-stage split is the structural backbone: the build stage carries compilers and dev dependencies that never reach production, while the final stage ships only the runtime and the application, which is where most of the size and security wins come from.
Pro tips
- Set
[base_image_pref]deliberately; distroless cuts attack surface hardest but complicates debugging, while alpine is friendlier - Match
[runtime]to where the image actually runs ("AWS ECR + ECS Fargate") so the build targets the right platform - Order your COPY steps so dependencies cache separately from source — this single change makes most rebuilds near-instant
- Verify the pinned base-image versions are current, since pinning to an old tag trades speed for stale security patches
- Test that the non-root user and read-only filesystem don't break paths your app writes to at runtime
- Treat the savings estimate as approximate and confirm the real size with a local build