Docker Best Practices: Smaller, Safer, Faster Images

DataFmt Team
#docker #devops #containers #security
5 min read

Docker Best Practices: Smaller, Safer, Faster Images

A 1.2 GB image is rarely necessary. Here is the playbook we apply to every Dockerfile.

1. Multi-stage builds

Build with the full SDK, ship with the runtime only:

FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM gcr.io/distroless/nodejs20
COPY --from=build /app/dist /app
CMD ["/app/server.js"]

2. Order layers by stability

COPY package*.json before COPY . so dependency layers cache across code changes.

3. Use .dockerignore

Exclude node_modules, .git, .env, dist, and tests. This dramatically shrinks the build context.

4. Pin everything

FROM node:20.11.0-bookworm-slim@sha256:abcd...

5. Run as non-root

RUN useradd -m app
USER app

Distroless and Chainguard images do this for you.

6. Health checks

HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget -qO- http://localhost:3000/health || exit 1

7. Scan and sign

  • docker scout or trivy for vulnerability scanning.
  • cosign sign for supply-chain attestations.

TL;DR

Multi-stage + distroless + pinned digests is the 80/20 of secure, lean container images.

Found this helpful? Try our free tools!

Explore Our Tools →