Skip to content
Back to Deployment

Optimizing Docker Images

Techniques for smaller, faster, more secure Docker images.

ContainersIntermediate

Why

Optimized images pull faster, use less disk, and have fewer vulnerabilities. Key techniques: .dockerignore, layer caching, distroless, and BuildKit.

When

Always optimize production images — faster deploys, lower costs, better security. Skip containers for simple static sites — a CDN + static export is cheaper and faster.

Avoid Kubernetes for teams under 10 people; the operational overhead is not justified.

How

1. .dockerignore — exclude node_modules, .git, tests 2. Layer order — copy package.json first, then source 3. Distroless — gcr.io/distroless/nodejs20, no shell 4. BuildKit — DOCKER_BUILDKIT=1 for parallel + cache 5. Slim base — alpine or debian-slim 6. Multi-arch — docker buildx for amd64 + arm64 7. Scan — docker scout or trivy for vulnerabilities

Example

# .dockerignore node_modules .git *.test.ts dist .env # Dockerfile — optimized layer order FROM node:20-alpine WORKDIR /app COPY package*.json ./ # deps first, cached RUN npm ci --omit=dev COPY . . # source last, changes often CMD ["node", "server.js"] # Distroless (smallest, most secure) FROM node:20 AS build WORKDIR /app COPY . . RUN npm ci && npm run build FROM gcr.io/distroless/nodejs20 COPY --from=build /app/dist /dist CMD ["/dist/server.js"] # BuildKit with cache mount # syntax=docker/dockerfile:1 FROM node:20-alpine RUN --mount=type=cache,target=/root/.npm npm ci

Common Problems

  • ⚠Large image — no .dockerignore, node_modules and .git included
  • ⚠Slow builds — wrong layer order, source copy invalidates deps cache
  • ⚠Configuration drift between environments — use infrastructure-as-code (Terraform/Pulumi) to keep dev/staging/prod identical

Best Practices

  • ✓Copy package.json before source — deps layer cached unless deps change
  • ✓Use distroless for production — no shell, no package manager, minimal attack surface
  • ✓Set up health checks and graceful shutdown — handle SIGTERM to drain in-flight requests before exit

FAQ