Home/Learn/Docker/Docker Images & Layers

Docker Images & Layers

Beginner
Fundamentals

Docker images are built from stacked read-only layers stored in a Union File System. Understanding layers is the key to writing efficient Dockerfiles and keeping image sizes small.

Overview

Every Dockerfile instruction (FROM, RUN, COPY, ADD) creates a new layer. Layers are content-addressed by SHA256 hash and shared across images — if two images share the same base layer, it is only stored once on disk. When a container starts, Docker adds a thin writable layer on top of the read-only image layers (Copy-on-Write semantics). This is why containers start instantly — the image layers are already on disk. Understanding layer ordering unlocks the most impactful Dockerfile optimisation: cache invalidation. Once a layer changes, all subsequent layers must be rebuilt.

Layer Visualisation

Think of layers as transparent acetate sheets stacked on top of each other. The final image is what you see through all the sheets combined. Each RUN, COPY, ADD instruction adds one sheet.

Docker layer stack — node app example
Layer 5 (COPY . .)              ← writable, specific to your app

Layer 4 (RUN npm ci)            ← node_modules, cached until package.json changes

Layer 3 (COPY package*.json ./) ← package files

Layer 2 (WORKDIR /app)          ← just sets a directory pointer

Layer 1 (FROM node:20-alpine)   ← ~120 MB base: Linux Alpine + Node runtime

         ────────────────────

         All layers = final image



# Inspect layers with:

docker history my-app:latest



IMAGE          CREATED       SIZE    COMMENT

7f2a1b3c9d4e   2 min ago    1.2MB   COPY . .

<missing>      2 min ago    45.1MB  RUN npm ci

<missing>      2 min ago    1.5KB   COPY package*.json ./

<missing>      2 min ago    0B      WORKDIR /app

<missing>      3 days ago   121MB   node:20-alpine

Cache Invalidation — The Critical Optimisation

Docker checks if a layer's instruction + context has changed. If yes, that layer and ALL layers below it are rebuilt from scratch. This is why dependency installation must come BEFORE source code copy — your source changes every build, but package.json changes rarely.

Dockerfile — cache-friendly ordering
# ❌ BAD: cache always invalidated (source changes → npm ci reruns every build)

FROM node:20-alpine

WORKDIR /app

COPY . .                     # copies everything including src — changes every commit

RUN npm ci                   # reruns even if package.json didn't change



# ✅ GOOD: npm ci only reruns when package.json changes

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./        # only these two files — stable

RUN npm ci                   # cached until package.json changes 🚀

COPY . .                     # src changes here, but npm ci is already cached

Reducing Image Size

Every layer adds to the final image size. Use Alpine base images (~5 MB vs Ubuntu ~80 MB), combine RUN commands to merge layers, and clean up in the same RUN step (not a later one, as the previous layer already captured the files).

bash — minimising layer size
# ❌ BAD: cache and disk wasteful

RUN apt-get update

RUN apt-get install -y curl git

RUN rm -rf /var/lib/apt/lists/*   # too late — previous layers captured the cache



# ✅ GOOD: single layer, clean up in same step

RUN apt-get update && \

    apt-get install -y --no-install-recommends curl git && \

    rm -rf /var/lib/apt/lists/*



# Check image size

docker images

# REPOSITORY   TAG       SIZE

# my-app       bad       389MB

# my-app       good      142MB



# Dive tool — interactive layer explorer

# docker run --rm -it wagoodman/dive my-app:latest

Key Points to Remember

  • 1Each Dockerfile instruction creates an immutable, cached layer.
  • 2Layers are shared across images via content-addressed SHA256 hashes.
  • 3Cache invalidation: once a layer changes, all subsequent layers rebuild.
  • 4Put stable instructions (base image, dependencies) before volatile ones (source code).
  • 5Combine RUN commands and clean up in the same layer to avoid bloat.
  • 6Alpine-based images are 10-20x smaller than Debian/Ubuntu-based ones.

Interview Questions

Sign in to ask Aria
1

Why should you copy package.json before copying source code in a Node.js Dockerfile?

2

How does Docker's Union File System work?

3

How do you reduce a Docker image size?

Ask Aria about Docker Images & Layers

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…