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.4---56# Dockerfile Builder78## Prerequisites & Dependencies9- Docker Engine 20.10+ (Docker Desktop or Podman with BuildKit enabled)10- Project source with a dependency manifest (`package.json`, `requirements.txt`, `go.mod`, `pom.xml`, ...)11- No API keys required; a `.dockerignore` must exist so secrets (`.env`, key files) never enter image layers1213## Execution Steps141. Choose slim, version-pinned base images: a toolchain image for the build stage, a minimal runtime base (`*-alpine`, `distroless`, or `*-slim`).152. Structure the file as multi-stage: compile/install in a `build` stage, copy only produced artifacts into the `runtime` stage.163. Order layers for cache efficiency: copy dependency manifests first, install dependencies, then copy source last.174. 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/*`).185. Add `HEALTHCHECK`, required `EXPOSE`/`ENV` declarations, and an exec-form `ENTRYPOINT`/`CMD`.196. Build, inspect layer history and image size, then scan for CVEs; iterate until size and vulnerability profile are acceptable.2021```dockerfile22# syntax=docker/dockerfile:1.723FROM node:20-alpine AS build24WORKDIR /app25COPY package.json package-lock.json ./26RUN npm ci --ignore-scripts27COPY src ./src28RUN npm run build && npm prune --omit=dev2930FROM gcr.io/distroless/nodejs20-debian12:nonroot AS runtime31WORKDIR /app32ENV NODE_ENV=production33COPY --from=build /app/dist ./dist34COPY --from=build /app/node_modules ./node_modules35EXPOSE 300036USER nonroot37HEALTHCHECK CMD ["node", "-e", "fetch('http://localhost:3000/health')"]38```3940```bash41DOCKER_BUILDKIT=1 docker build -t app:local .42docker history app:local --no-trunc43docker scout cves app:local44```45