The four concepts everything else is built on
Images, containers, volumes and networks. Learn these four and the rest of Docker becomes predictable — including the commands you have not read about yet.
Docker has a large command surface and a small conceptual one. There are four things. Everything in the CLI is an operation on one of them.
1. Images — the frozen filesystem
An image is a read-only filesystem plus metadata describing how to start a process in it. Think of it as a class. It does nothing on its own.
Images are built in layers, and this is the part worth understanding properly because it governs both build speed and image size. Each instruction in a Dockerfile produces one layer, and each layer stores only what changed from the layer beneath it:
┌─────────────────────────────┐
│ COPY . . │ ← your source code
├─────────────────────────────┤
│ RUN npm ci │ ← node_modules
├─────────────────────────────┤
│ COPY package*.json ./ │ ← dependency manifest
├─────────────────────────────┤
│ FROM node:22-alpine │ ← base image
└─────────────────────────────┘
Two consequences follow, and they drive most of Docker’s practical advice:
Layers are cached. Rebuilding only re-runs instructions from the first changed layer
downward. This is exactly why every Dockerfile you have seen copies package.json and installs
dependencies before copying the source — source changes on every commit, dependencies do not,
so putting them in that order keeps the expensive install cached.
Layers are shared. Ten images built FROM node:22-alpine store that base once on disk and
download it once.
2. Containers — the running process
A container is an image plus a thin writable layer plus a running process. If the image is a class, the container is an instance. One image, many containers.
The lifecycle is smaller than people expect:
created ──start──> running ──stop──> stopped ──rm──> gone
│ │
└─────start────────┘
A container exits when its main process exits. That is not a bug or a configuration option —
it is the definition. A container running a web server stays up because the server does not
return. A container running ls stops immediately because ls finishes.
The writable layer is the crucial detail: it is destroyed with the container. Everything your
application wrote — uploads, database files, logs — is gone when you docker rm it. Which brings
us to the next concept.
3. Volumes — where data actually lives
A volume is storage that exists outside the container’s lifecycle. Two kinds matter:
Named volumes — Docker manages the storage, you refer to it by name:
docker volume create pgdata
docker run -v pgdata:/var/lib/postgresql/data postgres:17
Use these for databases and anything the application owns. They survive docker rm, they perform
well on every platform, and Docker handles the location.
Bind mounts — you map a host directory into the container:
docker run -v "$PWD/src":/app/src node:22
Use these in development so your editor’s changes appear inside the container instantly, without a rebuild. Avoid them in production: you have just made the container depend on the host’s filesystem layout, which is the coupling you containerised to escape.
4. Networks — how containers find each other
Every container gets its own network namespace: its own interfaces, its own ports, its own
localhost. That last part trips up everyone at least once.
On a user-defined bridge network, Docker runs an embedded DNS server and containers resolve each other by container name:
docker network create appnet
docker run -d --name db --network appnet postgres:17
docker run -d --name api --network appnet myapi
# inside `api`, the database is reachable at db:5432
That is the entire mechanism, and it is why Compose “just works” — Compose creates a network and
names each container after its service, so postgres:5432 resolves from your app without you
configuring anything.
Publishing ports is separate. -p 8080:80 maps port 8080 on the host to port 80 in the
container. Without it, the container is reachable from other containers on its network but not
from your browser.
How the four fit together
docker build docker run
Dockerfile ──────────> Image ──────────────────> Container
│ │
│ ┌─────┴─────┐
(read-only, │ │
shared layers) Volume Network
(survives) (name-based DNS)
Every command you will meet operates on one of these. docker images, docker ps,
docker volume ls, docker network ls — four nouns, the same verbs.
Next: building a real image, one Dockerfile line at a time.