Card 04/ 07
Ordering a Dockerfile So the Dependency Install Stays Cached
Copy the dependency list, install, then copy the source, and a one-line edit builds in two seconds.
A Dockerfile keeps its dependency install cached when the files that rarely change are copied above the install and the files that change constantly are copied below it. For a Node.js project that means copying package.json and package-lock.json (the files that list its dependencies) first, installing, and copying the source last.
You start from a Dockerfile that copies the whole project with COPY . . before RUN npm ci, and you replace those two lines with the three below. The project must have both package.json and package-lock.json, because npm ci refuses to run without the lock file.
Reordering so a source edit stops reinstalling dependencies
Copy only what the install needs
COPY package.json package-lock.json ./These two files change when a dependency changes, and not when you edit a function. package-lock.json records the exact version of every package, so copying it alongside package.json means this layer, the cached result of the copy, changes exactly when the installed packages would.
Install, while nothing else has been copied
RUN npm cinpm ci installs exactly the versions the lock file records, which makes it the right install command for a build. This layer now depends on the two dependency files alone, so it survives every edit that does not touch them.
Copy the source last
COPY . .The layer that changes most often is now the last one, so a change to it invalidates only itself and what follows.
Measure it
time docker build -t my-api:1 . # after a one-line source edit
real 0m1.9sRebuild after a one-line source edit. It takes about two seconds, against roughly twelve for the same edit in the old order, because the install now comes from the cache.
You know it worked when a source-only edit shows CACHED on the RUN npm ci line. The rule applies beyond Node.js, because every ecosystem has the same two kinds of file: copy the dependency list (Maven's pom.xml, Python's requirements.txt, Go's go.mod), install, then copy the source.
← → move through sections and cards