liveBook · Manning

Build cache

As explained in Learn Docker in a Month of Lunches, Second Edition

An image layer cache is a build cache that stores previously generated image layers for reuse when their inputs have not changed.

A small application edit should not force every step of a Docker image build to run again. Docker’s image layer cache reuses a previously generated layer when its Dockerfile instruction and inputs have not changed. Reuse saves build time and avoids generating a duplicate layer. section 3.5

Docker checks for a cache match using a hash of the instruction and the contents of files it copies. If an input changes, Docker executes that instruction and every instruction after it, even when later instructions are unchanged. Put rarely changed instructions first and frequently changed files near the end of the Dockerfile. section 3.5

Listing 3.2 The optimized web-ping Dockerfile
FROM diamol/node:2e

CMD ["node", "/web-ping/app.js"]

ENV TARGET="blog.sixeyed.com" \
    METHOD="HEAD" \
    INTERVAL="3000"

WORKDIR /web-ping
COPY app.js .

In this optimized Dockerfile, the application’s app.js file is copied last. Changing that file leaves the preceding setup eligible for reuse. section 3.5

For a Java build, copy pom.xml and fetch Maven dependencies before copying the rest of the source and running mvn package. A source-code edit can then reuse the dependency layer when pom.xml has not changed. In a multi-stage Dockerfile, each stage has its own build cache, so changing a later stage need not rerun an earlier one. section 4.2 section 17.4

Listing 4.2 Dockerfile for building a Java app with Maven
FROM diamol/maven:2e AS builder

WORKDIR /usr/src/iotd
COPY pom.xml .
RUN mvn -B dependency:go-offline

COPY . .
RUN mvn package

# app
FROM diamol/openjdk:2e

WORKDIR /app
COPY --from=builder /usr/src/iotd/target/iotd-service-0.1.0.jar .

EXPOSE 80
ENTRYPOINT ["java", "-jar", "/app/iotd-service-0.1.0.jar"]

The Java Dockerfile separates dependency fetching from source compilation and copies the resulting JAR into a later stage. section 4.2

Check the effect of instruction order

Build the two Jenkins Dockerfiles, change their shared configuration file, then repeat the builds and compare how long they run. The optimized ordering keeps the large download ahead of the frequently changed configuration, allowing the download stage to come from the cache. section 17.4

Treat instruction order as something to test and refine: monitor build times as part of image optimization, alongside image size and push and pull times. section 17.4 section 17.5

How Learn Docker in a Month of Lunches, Second Edition covers it

How deep it goes
Explains hash-based matching, downstream invalidation, instruction ordering and stage caches, without specifying the hash algorithm.
Examples
Uses a changed JavaScript file, a Java Maven Dockerfile and a Jenkins configuration edit to show cache behavior.
What it assumes
Assumes familiarity with basic Dockerfile instructions while introducing the Maven commands needed for the Java example.
What you can do after
Operate/configure it by ordering Dockerfile steps for reuse, then comparing build times after a content change.
How it connects
Connects Dockerfile instruction order with image layers, multi-stage builds and Maven dependency fetching.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Docker in a Month of Lunches, Second Edition. The section links point to the parts of the book it draws on.