Docker
Beginner 14 min read Docker

Docker Images

Images are immutable, layered blueprints for containers. Learning how layers and build caching work is the key to fast, small and secure Docker images.

layersDockerfilebuild cacheimage sizedigestmulti-stage
Prerequisites: What is Docker?
Introduction

What is this?

A Docker image is a read-only template made of stacked filesystem layers. Each instruction in a Dockerfile creates one layer. When you build, Docker caches each layer; when you run, layers are mounted read-only and a thin writable layer is added on top.

Motivation

Why do you need it?

  • Layers make images shareable — the base OS layer is stored once and reused by every image built on it.
  • Build caching speeds up iteration: unchanged layers are reused instead of rebuilt.
  • Immutability means the artifact is identical in dev, staging and production.
  • Smaller images transfer faster and start quicker.
Think about it

Mental model

Imagine

A photo negative

Think of

A Docker image

A negative is a fixed template; every print made from it is identical. Every container from an image starts from the same immutable state.

Mechanics

How it works

  • The Dockerfile is a recipe of instructions, each becoming a layer in the final image.
  • On build, Docker checks its cache: if the instruction and its parent layers are unchanged, the cached layer is reused.
  • Changing a line invalidates that layer and every layer after it — so order matters.
  • Images are identified by repository:tag and a content-addressable digest (sha256).
  • A multi-stage build uses one image to compile and a separate slim image to run, dropping build toolchain weight.

Layers of a Docker image built with build cache.

FROM node:20-alpine
WORKDIR /app
COPY package*.json
RUN npm ci
COPY . .
CMD ["npm","start"]
Reference

Key commands

docker images

List local images with their tags and sizes.

docker build -t myapp:1.0 .

Build an image from the Dockerfile in the current directory.

docker build --no-cache -t myapp:1.0 .

Rebuild without using any cached layers.

docker history myapp:1.0

Show every layer in the image and its size.

docker rmi myapp:1.0

Remove an image and its layers.

Hands-on

Examples

A lean Node.js Dockerfile

A lean Node.js Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
ENV NODE_ENV=production
USER node
EXPOSE 3000
CMD ["node", "server.js"]

Dependency files are copied before the source so npm ci is cached until deps change. The app runs as the non-root 'node' user, and the alpine base keeps the image small.

Real world

In production

  • CI builds images once per commit and tags them with commit SHA for traceability.
  • Multi-stage builds produce runtime-only images that exclude compilers and SDKs.
  • Distroless and scratch base images minimize attack surface and size.
  • Vulnerability scanning (Trivy, Grype) gates image promotion in the pipeline.
Guidelines

Best practices

  • Order instructions from least to most frequently changing to maximize cache hits.
  • Pin base image versions, never FROM node:latest.
  • Use multi-stage builds and minimal bases (alpine, distroless, scratch).
  • Add a .dockerignore to keep build context and secrets out of the image.
  • Use COPY over ADD unless you need tar auto-extraction or remote URLs.
Watch out

Common mistakes

  • Copying source before dependencies, invalidating the npm ci cache on every change.
  • Including secrets via ARG/ENV that end up in image layers.
  • Running builds as root inside the image.
  • Leaving debuggers, test files and .git in production images.
Root cause analysis

Common issues

Error
failed to solve: process ... did not complete successfully
Root cause

A RUN instruction's command exited non-zero.

Fix

Add a temporary RUN with the failing command and inspect output, or use docker build --no-cache --progress=plain.

Error
ERROR: failed to authorize: failed to fetch anonymous token
Root cause

Registry rate limit or no network from the build host.

Fix

Authenticate with docker login, retry, and prefer a smaller base image to reduce pull volume.

Error
COPY failed: stat ... no such file or directory
Root cause

Path is outside the build context or excluded by .dockerignore.

Fix

Verify the file exists inside the context directory and isn't in .dockerignore.

When things break

Debugging tips

  • docker history to find which layer bloats the image.
  • docker build --progress=plain to see exactly which steps ran or used cache.
  • docker build --no-cache to rule out a poisoned cache.
  • docker run --entrypoint sh IMAGE to explore the built filesystem.
Interviews

Interview checkpoint

Practice

Hands-on lab

Build a Production-Ready Image
35 min · intermediate
In progress
Objectives
  • Write an optimized Dockerfile
  • Use build cache correctly
  • Reduce final image size with a multi-stage build
  • Inspect image layers

Build a Production-Ready Image

35 min · intermediate

0/5 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

Which statement about Docker image layers is true?

2

What happens to the cache when you change COPY . . in the middle of a Dockerfile?

Quick reference

Cheat sheet

Build & inspect
docker build -t app:tag .Build an image
docker imagesList local images
docker history app:tagShow layer stack
docker rmi app:tagDelete an image
Go deeper

Official documentation