Docker layers, caching and smaller images

A good Dockerfile is mostly about ordering. Put the things that change least at the top and keep the runtime surface small.

Docker layers, caching and smaller images cover illustration

Docker caches each instruction as a layer. If a layer changes, every later layer is rebuilt. Copying the entire repository before installing dependencies means every code change re-installs everything.

DockerfileDockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=build /app/.output ./.output
USER node
CMD ["node", ".output/server/index.mjs"]

Keep the runtime boring

  • Use a multi-stage build so compilers and development dependencies do not ship in the final image.
  • Pin a version instead of latest. A moving tag makes yesterday’s deploy unreproducible.
  • Run as a non-root user and drop capabilities you do not need.
Something to add?

Corrections and technical review are welcome. Tell us what we missed.

Send a correction