You write a Dockerfile, run docker build, and get an image.
But what’s really happening under the hood? Docker isn’t just “building” your app — it’s assembling a stack of immutable filesystem layers.
Docker doesn’t build applications — it builds filesystem snapshots layer by layer.
Let’s break it down.
1. What is a Docker Image, Really?
A Docker image is not a single file.
It’s a stack of read-only layers.
Every instruction in your Dockerfile creates a new layer:
-
FROM→ Base layer -
RUN→ Executes command and snapshots the result -
COPY/ADD→ Adds files into a new layer -
ENV,WORKDIR,CMD→ Metadata layers
These layers are:
- Immutable
- Content-addressed (using SHA256)
- Reusable across images and builds
This design is what makes Docker fast and efficient.
2. How Docker Build Works (Step by Step)
When you run docker build .:
- Docker CLI sends the build context (files + Dockerfile) to the daemon.
- BuildKit (Docker’s modern build engine) takes control.
- Dockerfile is read from top to bottom.
- For each instruction:
- Docker checks the cache.
- Cache hit → Reuses existing layer (very fast).
- Cache miss → Executes the instruction and creates a new layer.
- All layers are stacked to create the final image.
3. Layer Caching – The Real Superpower
Docker follows one strict rule:
If a layer changes, Docker invalidates that layer and all subsequent layers.
Bad Order (Slow Builds)
FROM node:20
COPY . . # Code changes frequently
RUN npm install # This runs every time
Good Order (Fast Builds)
FROM node:20
COPY package*.json ./ # Rarely changes
RUN npm install # Cached most of the time
COPY . .
Rule of Thumb: Put stable things (dependencies) at the top. Put frequently changing things (your code) at the bottom.
4. BuildKit vs Legacy Builder
| Feature | Legacy Builder | BuildKit (Recommended) |
|---|---|---|
| Speed | Slow | Much Faster |
| Parallel Execution | No | Yes |
| Cache Intelligence | Basic | Advanced |
| Multi-platform Build | Difficult | Easy |
| Secret Handling | Risky | Secure |
Enable BuildKit:
DOCKER_BUILDKIT=1 docker build .
5. Multi-Stage Builds (The Pro Move)
# Build Stage
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production Stage
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]
Benefits: Smaller image, faster deployment, better security.
Multi-stage builds ensure only the final artifacts are kept — everything else is discarded.
6. Quick Debugging Tips
- Build is slow → Reorder your Dockerfile
- Cache not working →
docker build --no-cache - Image too big → Use multi-stage +
.dockerignore - See detailed output →
docker build --progress=plain .
7. Under the Hood (How Layers Actually Work)
Docker uses a Union File System (like OverlayFS) to combine layers.
- Lower layers → read-only
- Top layer → writable (when container runs)
To you, it looks like a single filesystem.
Internally, it’s multiple layers merged together.
Summary
A Dockerfile is not just a list of commands.
It’s a performance blueprint for building layered, cached, and efficient images.
Master layer order and caching, and your builds will go from slow and frustrating to fast and predictable.
🔜 Next in Series
Docker Storage & Volumes Internals – Why containers eat disk space and how to control it.
Top comments (0)