The layered filesystem & build cache
Why instruction order makes builds fast.
Every instruction in a Dockerfile that changes the filesystem produces a layer, and an image is just those layers stacked on top of each other, read-only. Layers are content-addressed and shared: if two images start FROM the same base, that base is stored once on disk and pulled once over the network. When you run a container, Docker adds one thin writable layer on top of the image’s read-only stack — that is where the running container’s changes go.
The build cache
Docker caches layers and reuses them on the next build — until it hits the first instruction whose inputs changed, after which every layer below is rebuilt. That single rule dictates how you order a Dockerfile: put the things that change rarely (installing dependencies) before the things that change every commit (copying source). Get the order right and rebuilds drop from minutes to seconds; get it wrong and every one-line code change reinstalls all your dependencies.
# SLOW: any source change busts the cache for npm ci, reinstalling every buildCOPY . .RUN npm ci# FAST: deps only reinstall when package.json changes, not on every code editCOPY package*.json ./RUN npm ciCOPY . .
Why this matters beyond speed
Layer sharing also makes pulls cheap: when you push a new version, only the changed layers upload, and nodes that already have the base only download the small top layers. Fast, well-ordered builds are not just a convenience — they are what makes it practical to rebuild and redeploy on every commit.