Image Layers & Caching
Each Dockerfile instruction creates a cached layer, and understanding layers helps you build faster, smaller images.
Docker images are built in layers. Every instruction in your Dockerfile creates a new read-only layer stacked on top of the previous ones.
Why layers matter
- Caching — if a layer has not changed, Docker reuses the cached version instead of rebuilding it, making builds much faster.
- Sharing — images that share base layers only store them once on disk.
Ordering for cache hits
Copy files that rarely change (like package.json) and install dependencies before copying your full source code. That way, editing a source file does not bust the dependency-install cache.
Example
# Fewer, cleaner layers: install and clean up in one RUN
FROM debian:12-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*When to use it
- A developer reorders Dockerfile instructions to put rarely changed steps first, so code changes don't invalidate the dependency layer cache.
- A build engineer notices a 2 GB image and uses docker history to identify which layer added an unexpectedly large file.
- A CI team leverages layer caching to keep package install steps from re-running on every build, cutting build time from 4 minutes to 30 seconds.
More examples
Inspect image layer history
Lists every layer in the image with its size, creation time, and the Dockerfile instruction that created it.
docker image history myapp:1.0
# Show full command for each layer
docker image history --no-trunc myapp:1.0Dockerfile with cache-friendly order
Puts slow, rarely-changing steps (npm install) before frequently-changing steps (source copy) to maximise cache hits.
FROM node:20-alpine
WORKDIR /app
# Copy dependencies first — only re-runs when package.json changes
COPY package*.json ./
RUN npm ci
# Copy source last — changes here don't bust the npm layer
COPY . .Collapse RUN commands to merge layers
Chains commands with && so the cache cleanup happens in the same layer as the install, preventing extra disk usage.
# Bad: creates 3 layers
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# Good: one layer, smaller image
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
Discussion