Skip to content

Layer Caching

Many instructions in a Dockerfile create a discrete layer.

You can think of a layer as a snapshot of the filesystem within the image at a specific point in time.

That’s where caching comes in.

Docker can reuse previously built layers from its cache if the relevant inputs (the files we are copying or the commands we are running) have not changed.

Layer Caching

We want to put the instructions that change the least frequently at the top of the Dockerfile, and the instructions that change the most frequently at the bottom of the Dockerfile.

This way, Docker can reuse the cached layers as much as possible.

Here is why we usually split up our copying into two steps:

COPY package*.json ./
RUN npm install
COPY . .

That exact sequencing is intentional.

Flowchart diagram showing Docker layer caching, illustrating a cache hit on the npm install step but a cache miss invalidating the subsequent source code COPY step

If package.json and package-lock.json have not changed since our last build, Docker will safely reuse the cached layer where dependencies were npm installed.

Then, if we only change our application source code (e.g. server.js), the cache only invalidates at the second COPY step. Docker can skip re-running npm install entirely.

That makes our day-to-day rebuilds exponentially faster.

Intentional Architecture

It’s a tiny structural choice, but it holds a very real time payoff. Good Dockerfiles are ordered from least-frequently-changed (base images, dependencies) to most-frequently-changed (source code).

If you do this instead, it will technically work:

COPY . .
RUN npm install

…but it breaks the caching model.

Slower and Annoying

If we copy everything first, then even a tiny modification to a minor route file will invalidate that COPY layer. As a result, Docker has to re-run our npm install, and every subsequent step each and every single time we make even the slightest change to any code.


Docker Build Caching

It’s not just git that gets to ignore files. Docker does, too.