Docker and Kubernetes course menu
Docker Layers, Build Cache and .dockerignore Explained
Understand image layers and the build cache, order Dockerfile instructions for fast rebuilds, reduce image size, and use .dockerignore to keep files out of images.
On this page
Each instruction in a Dockerfile creates a layer. Docker saves these layers, and reuses them when nothing has changed. Understanding this is the key to fast builds and small images.
The build cache#
mkdir app
cd app
echo "v1" > code.txt
echo "deps" > deps.txt
cat > Dockerfile <<'EOF'
FROM alpine:3.24
COPY deps.txt .
RUN sleep 2 && echo "installing" > installed.txt
COPY code.txt .
EOF
docker build -q -t cachedemo . > /dev/null
echo "Built"BuiltBuild again, with no changes:
docker build --progress=plain -t cachedemo . 2>&1 | grep -E '^#[0-9]+ (CACHED|\[[0-9])'#4 [1/4] FROM docker.io/library/alpine:3.24
#6 [2/4] COPY deps.txt .
#6 CACHED
#7 [3/4] RUN sleep 2 && echo "installing" > installed.txt
#7 CACHED
#8 [4/4] COPY code.txt .
#8 CACHEDEvery step after FROM was CACHED, so the build was nearly instant.
What breaks the cache#
Docker checks each step in order. When one step changes, that step and all those after it run again. Change code.txt, which is copied last:
echo "v2" > code.txt
docker build --progress=plain -t cachedemo . 2>&1 | grep -E '^#[0-9]+ (CACHED|\[[0-9])'#4 [1/4] FROM docker.io/library/alpine:3.24
#6 [2/4] COPY deps.txt .
#6 CACHED
#7 [3/4] RUN sleep 2 && echo "installing" > installed.txt
#7 CACHED
#8 [4/4] COPY code.txt .The slow install step stayed cached, because it comes before the change.
Order matters#
The rule is that things which change rarely go first, and things which change often go last. A typical app changes its code all the time, and its dependencies only occasionally:
# Slow: any code change reinstalls everything
COPY . .
RUN pip install -r requirements.txt# Fast: dependencies are reinstalled only when requirements.txt changes
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .Layers and size#
Layers only add. Deleting a file in a later step hides it, but the earlier layer still contains it:
cd ~
mkdir size
cd size
cat > Dockerfile <<'EOF'
FROM alpine:3.24
RUN head -c 20000000 /dev/urandom > /big.bin
RUN rm /big.bin
EOF
docker build -q -t size-bad . > /dev/null
cat > Dockerfile <<'EOF'
FROM alpine:3.24
RUN head -c 20000000 /dev/urandom > /big.bin && rm /big.bin
EOF
docker build -q -t size-good . > /dev/null
docker images --format '{{.Repository}} {{.Size}}' | grep sizesize-good 8.42MB
size-bad 28.4MBBoth images contain the same files, but one is about 20 MB bigger. So clean up in the same RUN that created the mess:
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*.dockerignore#
docker build first sends the whole folder, the build context, to the daemon. A .dockerignore file excludes things you do not want, which makes builds faster, and keeps secrets out of images:
cd ~
mkdir ctx
cd ctx
mkdir node_modules
echo "x" > node_modules/lib.js
echo "x" > debug.log
echo "API_KEY=secret" > .env
echo "code" > app.js
cat > .dockerignore <<'EOF'
node_modules
.git
.env
*.log
Dockerfile
EOF
cat > Dockerfile <<'EOF'
FROM alpine:3.24
WORKDIR /app
COPY . .
CMD ["ls", "-A"]
EOF
docker build -q -t ctx . > /dev/null
docker run --rm ctx.dockerignore
app.jsWithout .dockerignore, COPY . . would have put your .env file inside the image.
Force a rebuild#
--no-cache ignores the cache, and --pull fetches a newer base image. Use them to pick up security updates:
docker build --no-cache --pull -t app:1.0 .Common mistakes#
Practice#
Practice exercise
Print the layers of size-bad with docker history, showing only the sizes of its top two lines, to see where the size came from.
Show solution
docker history --format '{{.Size}}' size-bad | head -n 20B
20MBThe rm layer is empty, and the layer before it holds the 20 MB.
Key takeaway#
Next: Containerising a Python App.
Finished this lesson?
Related lessons
Recommended Docker and Kubernetes resources
- Docker Deep Dive by Nigel Poulton
A practical guide to how Docker works, for readers who have finished the basics.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.