Docker Basics
Ship the environment with the code — images, containers, and the difference between them.
45 minDifficulty 3/5docker · infraAI-writtenWritten by a model on 16 August 2026 and not yet read by a person. Checked automatically: schema, the pedagogical rules the hand-written material is held to, and every diagram parsed for real.
Before this
Why this exists
"It works on my machine" is a genuine, specific technical problem: a slightly different Node version, a missing system library, an OS-specific quirk, and code that ran perfectly on a laptop fails mysteriously on the server. Docker's entire premise is packaging the application TOGETHER with the exact environment it needs — the runtime, the libraries, the OS-level dependencies — so that environment difference stops being a variable at all.
The mental model
An IMAGE is a blueprint — a read-only snapshot of a filesystem plus instructions for what to run, built once. A CONTAINER is a running instance of that image — a live, isolated process with its own filesystem view, started fresh from the image each time. The same relationship as a class and an object: one image, many containers can run from it simultaneously, each isolated from the others.
How it works
Containers share the host's kernel, unlike a full virtual machine
A virtual machine virtualizes an entire computer, including its own kernel — heavyweight, with real overhead per VM. A container shares the HOST machine's kernel and only isolates the process's view of the filesystem, network, and other resources — dramatically lighter weight, which is why you can run dozens of containers on a machine that could only run a handful of full VMs.
An image is built from a Dockerfile, a declarative recipe
A Dockerfile lists, step by step, how to construct the image: start from a base (`FROM node:20`), copy in application files, install dependencies, specify what command runs when a container starts. `docker build` executes these instructions once, producing a reusable image; `docker run` starts a container FROM that already-built image, instantly, with no rebuild needed.
A container's filesystem changes disappear when it stops, unless explicitly persisted
By default, anything written inside a running container (a log file, a temp file, a database's actual data) is LOST the moment that container is removed — the container's filesystem is ephemeral, layered on top of the immutable image. Data that needs to survive beyond a single container's lifetime (a database's actual data files) must be explicitly mounted from the host or a separate persistent volume.
Networking between containers is explicit, not automatic
Two containers don't automatically see each other's ports or share a network by default — they need to be explicitly connected (via a shared Docker network, or a tool like Docker Compose that wires this up declaratively) before one can reach the other, say an application container talking to a database container. This is a deliberate isolation default, not an oversight.
The mechanism
A Dockerfile's instructions are executed once by `docker build`, producing an immutable image containing the application and everything it needs to run. `docker run` starts a new, isolated container process from that image — the container gets its own filesystem view (layered on the image, writable on top) and, by default, its own isolated network namespace, separate from the host and other containers unless explicitly connected.
flowchart LR D[Dockerfile] -->|docker build| I[Image - immutable blueprint] I -->|docker run| C1[Container 1 - running instance] I -->|docker run| C2[Container 2 - another instance] C1 -.->|writes lost on stop, unless volume mounted| Ephemeral[ephemeral filesystem]
What people get wrong
- A Docker container is essentially a lightweight virtual machine.
- A container shares the host's kernel and only isolates process-level resources (filesystem view, network namespace); a VM virtualizes entire hardware, including its own separate kernel — the isolation mechanism and overhead are fundamentally different, not just a matter of degree. This distinction matters practically: a container can't run a different KERNEL than the host (a Linux container needs a Linux host kernel), which a full VM has no such restriction on.
- Data written inside a running container is safely persisted as long as the container keeps running.
- It's persisted only as long as that SPECIFIC container exists — removing the container (not just stopping it, but actually deleting it) discards its writable layer entirely, including any data that wasn't explicitly stored in a mounted volume. This is a common, sometimes costly mistake with containerized databases specifically — running a database in a container without a mounted volume means a container restart or replacement can silently wipe all its data.
- Building a Docker image and running a container are essentially the same operation, just different commands.
- Building happens ONCE, producing a reusable artifact (the image); running can happen MANY times from that same image, each producing an independent, isolated container — conflating the two obscures why you'd rebuild only when the Dockerfile or its inputs change, but can run/stop/restart containers freely without rebuilding. Understanding this separation is what makes Docker's caching and speed make sense — running doesn't require repeating the (often slower) build step at all.
When not to use it
- You need a database's actual data to survive container restarts, upgrades, or replacements.
- An explicitly mounted volume (a named Docker volume, or a bind mount to a host directory) — never rely on a container's own ephemeral, writable layer for anything that needs to persist.
- You're running Windows-specific software that fundamentally requires the Windows kernel, on a Linux host.
- A full virtual machine, not a container — since containers share the host kernel, a Linux host cannot run a container requiring the Windows kernel (Windows containers require a Windows host, and vice versa).
Terms
- Image
- — An immutable, read-only blueprint containing an application and its dependencies, built from a Dockerfile, from which containers are started.
- Container
- — A running, isolated instance of an image, with its own writable filesystem layer and (by default) isolated network namespace.
- Dockerfile
- — A declarative set of instructions describing how to build an image, step by step.
- Volume
- — A mechanism for persisting data beyond a single container's lifetime, mounted from the host or a managed storage location, independent of the container's own ephemeral filesystem.
In an interview
Why is running a PostgreSQL database in a Docker container without a mounted volume a risky setup for anything beyond local testing?
- a container's writable filesystem layer is ephemeral — it's discarded when the container is removed
- without an explicitly mounted volume, all the database's actual data files live only in that ephemeral layer
- a container restart, replacement, or crash-and-recreate cycle would permanently lose all the data, unless a volume is properly configured
Can you recall it?
What's the relationship between a Docker image and a container, and why can multiple containers run from one image simultaneously?