How Layers Work (The Transparent Sheet Analogy)
LEVEL 0
The Problem
You have two images:
python:3.11— 1.01 GBmyappbuiltFROM python:3.11— also shows 1.01 GB
Did Docker really store 2 GB? No — it stored about 1.01 GB. But how?
And when you run 10 containers from myapp, are there 10 copies of that 1.01 GB? No — still about 1.01 GB. How does that work?
The answer is layers.
LEVEL 1
The Concept — Transparent Sheets (Acetate Layers)
The Concept
Remember old-school overhead projectors? Or traditional animation?
Animators draw backgrounds on one transparent sheet. Characters on another sheet. Props on a third. They stack the sheets, and you see the complete picture.
If the character moves but the background doesn’t, you only redraw the character sheet. The background sheet stays the same.
Docker images work exactly like this.
Each layer is a transparent sheet. The base image is the background — maybe Ubuntu with all its files. The next layer adds Python on top. The next layer adds your dependencies. The final layer adds your code.
When you “look at” the image (or run a container), Docker stacks all the sheets and you see the complete filesystem.
The useful property: Layers are shared. If 10 images all start with FROM python:3.11-slim, they all share the same base layers. It’s stored once, referenced many times.
LEVEL 2
The Mechanics — Layer Structure
The Mechanics
Each Instruction Creates a Layer
FROM python:3.11-slim # Layer 1: Base image (actually multiple layers)
WORKDIR /app # Layer 2: Create directory
COPY requirements.txt . # Layer 3: Add file
RUN pip install ... # Layer 4: Install packages
COPY . . # Layer 5: Add code
CMD ["python", "app.py"] # Layer 6: Metadata (no filesystem change)
Layers Are Read-Only
Once a layer is created, it never changes. It’s immutable. This is crucial for sharing — if layers could change, you couldn’t safely share them.
Layers Are Identified by Content Hash
Each layer has an ID (SHA256 hash) based on its contents. Two layers with identical contents have the same ID. This enables deduplication.
Image = Stack of Layer References
An image doesn’t contain layers — it references them. The image says “I’m made of layers A, B, C, D.” Those layers exist separately in storage.
LEVEL 3
Visualizing the Stack
┌─────────────────────────────────────────┐
│ Container Writable Layer │ ← Read-write
├─────────────────────────────────────────┤
│ Layer 5: COPY . . (your code, 2MB) │ ← Read-only
├─────────────────────────────────────────┤
│ Layer 4: RUN pip install (45MB) │ ← Read-only
├─────────────────────────────────────────┤
│ Layer 3: COPY requirements.txt (1KB) │ ← Read-only
├─────────────────────────────────────────┤
│ Layer 2: WORKDIR /app (0B metadata) │ ← Read-only
├─────────────────────────────────────────┤
│ Layer 1: python:3.11-slim (131MB) │ ← Read-only (shared!)
└─────────────────────────────────────────┘
When you access a file:
- Docker looks in the top layer first
- If not found, looks in the next layer down
- Continues until the file is found
- The first match wins
LEVEL 4
Why Layers Matter
Storage Efficiency
10 images based on python:3.11-slim don’t store 10 copies of Python. They store 1 copy and reference it 10 times.
Build Speed
When you rebuild an image, unchanged layers are reused from cache. Only modified layers (and those after) are rebuilt.
Network Efficiency
When you pull an image, Docker only downloads layers you don’t already have. If you have python:3.11-slim and pull a new image based on it, you only download the new layers.
Container Startup Speed
Containers don’t copy image layers — they just reference them. Starting a container is nearly instant because no large file copies are needed.