Dockerfile Builder
Prerequisites & Dependencies
- Docker Engine 20.10+ (Docker Desktop or Podman with BuildKit enabled)
- Project source with a dependency manifest (
package.json, requirements.txt, go.mod, pom.xml, ...)
- No API keys required; a
.dockerignore must exist so secrets (.env, key files) never enter image layers
Execution Steps
- Choose slim, version-pinned base images: a toolchain image for the build stage, a minimal runtime base (
*-alpine, distroless, or *-slim).
- Structure the file as multi-stage: compile/install in a
build stage, copy only produced artifacts into the runtime stage.
- Order layers for cache efficiency: copy dependency manifests first, install dependencies, then copy source last.
- Harden security: run as a non-root user (
USER), never bake secrets via ARG, and clean package caches (--no-cache, rm -rf /var/lib/apt/lists/*).
- Add
HEALTHCHECK, required EXPOSE/ENV declarations, and an exec-form ENTRYPOINT/CMD.
- Build, inspect layer history and image size, then scan for CVEs; iterate until size and vulnerability profile are acceptable.
# syntax=docker/dockerfile:1.7
FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --ignore-scripts
COPY src ./src
RUN npm run build && npm prune --omit=dev
FROM gcr.io/distroless/nodejs20-debian12:nonroot AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
EXPOSE 3000
USER nonroot
HEALTHCHECK CMD ["node", "-e", "fetch('http://localhost:3000/health')"]
DOCKER_BUILDKIT=1 docker build -t app:local .
docker history app:local --no-trunc
docker scout cves app:local
1---2name: dockerfile-builder3description: Draft efficient, secure, and minimal multi-stage Dockerfiles.4metadata:5 source: skills/dockerfile-builder/dockerfile-builder.md6---78# Dockerfile Builder910## Prerequisites & Dependencies11- Docker Engine 20.10+ (Docker Desktop or Podman with BuildKit enabled)12- Project source with a dependency manifest (`package.json`, `requirements.txt`, `go.mod`, `pom.xml`, ...)13- No API keys required; a `.dockerignore` must exist so secrets (`.env`, key files) never enter image layers1415## Execution Steps161. Choose slim, version-pinned base images: a toolchain image for the build stage, a minimal runtime base (`*-alpine`, `distroless`, or `*-slim`).172. Structure the file as multi-stage: compile/install in a `build` stage, copy only produced artifacts into the `runtime` stage.183. Order layers for cache efficiency: copy dependency manifests first, install dependencies, then copy source last.194. Harden security: run as a non-root user (`USER`), never bake secrets via `ARG`, and clean package caches (`--no-cache`, `rm -rf /var/lib/apt/lists/*`).205. Add `HEALTHCHECK`, required `EXPOSE`/`ENV` declarations, and an exec-form `ENTRYPOINT`/`CMD`.216. Build, inspect layer history and image size, then scan for CVEs; iterate until size and vulnerability profile are acceptable.2223```dockerfile24# syntax=docker/dockerfile:1.725FROM node:20-alpine AS build26WORKDIR /app27COPY package.json package-lock.json ./28RUN npm ci --ignore-scripts29COPY src ./src30RUN npm run build && npm prune --omit=dev3132FROM gcr.io/distroless/nodejs20-debian12:nonroot AS runtime33WORKDIR /app34ENV NODE_ENV=production35COPY --from=build /app/dist ./dist36COPY --from=build /app/node_modules ./node_modules37EXPOSE 300038USER nonroot39HEALTHCHECK CMD ["node", "-e", "fetch('http://localhost:3000/health')"]40```4142```bash43DOCKER_BUILDKIT=1 docker build -t app:local .44docker history app:local --no-trunc45docker scout cves app:local46```47