Layers & Size
A Docker image isn't one monolithic file — it's read-only layers stacked on top of each other. Each Dockerfile instruction creates one layer, and at run time a writable container layer is added on top so the whole stack looks like a single filesystem. Identical layers are shared between images and cached, which makes instruction order the thing that decides your build speed — and what you leave in the final image the thing that decides its size. A multi-stage build throws the build-only layers away wholesale, taking the same app from over a gigabyte down to a hundred-odd megabytes.
01Layers & Size
Concept at a GlanceA Docker image isn't one monolithic file. It's read-only layers stacked on top of each other, and each Dockerfile instruction creates one layer.
FROM node:20-alpine · lay the base image at the bottom. It's a 140 MB floor holding Alpine Linux and the Node runtime.
COPY package*.json · copy only the dependency manifest first. It's a thin 4 KB layer, but the point is that it changes far less often than your source.
RUN npm ci · install the dependencies. A 180 MB node_modules becomes a single layer — the heaviest one, and the one you least want to rebuild.
COPY . . · add the application source last. Putting what changes most often on top is the heart of layer design.
That's the image. A union filesystem overlays the four layers so they look like one filesystem — base on the inside, newest on the outside.
Running a container adds one more writable layer on top of the image. Every change while it runs is recorded only here, never touching the layers below (copy-on-write).
Changed only the source? Then only the top layer differs. The three layers below are reused straight from cache and the rebuild finishes in seconds.
Touch package.json instead and every cache above it is invalidated — the build reruns from npm ci and stretches to minutes. Instruction order is build speed.
But the image you just stacked is 1.1 GB. Build it in a single stage and everything made along the way stays in the final image. Height is size.
The biggest block is devDependencies at 420 MB: the TypeScript compiler, the bundler, the test runner. Used only at build time, never at run time.
The python·make·g++ installed to compile native modules is still there too, 190 MB of it. Tools left behind are also attack surface.
What actually runs is the blue sliver — dist/, 12 MB. Barely 1 % of 1.1 GB. That thin band is the reason the whole rest was carried around.
Multi-stage keeps a separate build stage and copies only the output forward with COPY --from=builder. The earlier stage never reaches the final image.
The grey mass disappears wholesale. What remains is the slim runtime at 140 MB, runtime dependencies at 3 MB, and that same dist/ at 12 MB.
02 Understand It Simply
For EveryoneAn image is a stack of read-only layers, one per Dockerfile instruction. A union filesystem presents them as a single filesystem, and changing a lower layer invalidates the cache of every layer above it.
Dockerfile instructions like FROM, COPY, and RUN each create a read-only layer, and a union filesystem overlays them into one view.
Start a container and a writable layer is added on top — every change is recorded only there (copy-on-write).
Changing a layer invalidates the cache of every layer above it, so the key is to put what rarely changes (installing dependencies) low and what changes constantly (your source) high.
- –Ordering Dockerfile instructions
- –raising build cache hit rates
- –shrinking image size
- –and understanding how multiple images share base layers
03 Frequently Asked Questions
FAQWhat is Layers & Size?+
A Docker image isn't one monolithic file — it's read-only layers stacked on top of each other. Each Dockerfile instruction creates one layer, and at run time a writable container layer is added on top so the whole stack looks like a single filesystem. Identical layers are shared between images and cached, which makes instruction order the thing that decides your build speed — and what you leave in the final image the thing that decides its size. A multi-stage build throws the build-only layers away wholesale, taking the same app from over a gigabyte down to a hundred-odd megabytes.
Where is Layers & Size used?+
Ordering Dockerfile instructions, raising build cache hit rates, shrinking image size, and understanding how multiple images share base layers.
What's a simple analogy for Layers & Size?+
An image is a stack of read-only layers, one per Dockerfile instruction. A union filesystem presents them as a single filesystem, and changing a lower layer invalidates the cache of every layer above it.
