Docker Tutorial · Building Images · Lesson 8 of 26
Layer Caching and Fast Builds
Order Dockerfile instructions so dependency installs are cached and code changes rebuild in seconds.
How the cache works
Docker reuses a cached layer until it reaches an instruction whose inputs changed (the instruction text, or the
checksums of files a COPY reads). Every instruction after that is rebuilt.
So copy dependency manifests and install dependencies before copying the rest of the source:
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt # cached until requirements.txt changes
COPY . . # code changes only invalidate from here
# a throwaway builder gives this demo its own empty build cache
docker buildx create --name rc-cache-demo --driver docker-container > /dev/null
trap 'docker buildx rm -f rc-cache-demo > /dev/null 2>&1; docker image rm -f rc-cache:1 > /dev/null 2>&1' EXIT
echo "requests==2.32.5" > requirements.txt
echo "print('v1')" > app.py
cat > Dockerfile <<'EOF'
FROM python:3.14-slim
WORKDIR /app
COPY requirements.txt .
RUN echo "installing dependencies (slow step)" && sleep 2
COPY app.py .
CMD ["python", "app.py"]
EOF
# list each step as "cached" or "built" from BuildKit's plain progress output
build() {
docker buildx build --builder rc-cache-demo --load --progress=plain -t rc-cache:1 . 2>&1 |
awk '/^#[0-9]+ \[[0-9]\/[0-9]\] (RUN|COPY|WORKDIR)/ {n=$1; sub(/^#[0-9]+ /, ""); step[n]=$0}
/^#[0-9]+ CACHED/ {cached[$1]=1}
END {for (n in step) print step[n] " -> " (n in cached ? "cached" : "built")}' | sort
}
echo "--- first build"; build
echo "print('v2')" > app.py
echo "--- after editing app.py"; build
docker run --rm rc-cache:1
Output
--- first build [2/5] WORKDIR /app -> built [3/5] COPY requirements.txt . -> built [4/5] RUN echo "installing dependencies (slow step)" && sleep 2 -> built [5/5] COPY app.py . -> built --- after editing app.py [2/5] WORKDIR /app -> cached [3/5] COPY requirements.txt . -> cached [4/5] RUN echo "installing dependencies (slow step)" && sleep 2 -> cached [5/5] COPY app.py . -> built v2
Run this on your computer — see “Get Started” for setup.
BuildKit also offers cache mounts (RUN --mount=type=cache,target=/root/.cache/pip ...) and remote caches for
CI. See Docker build cache.
Test yourself
Why copy requirements.txt before the rest of the source code?
It makes images smallerSo the dependency install layer stays cached when only code changesDocker requires itTo hide the source
Show answer
Answer: So the dependency install layer stays cached when only code changes
Any change to copied files invalidates that layer and everything after it.