Docker Fundamentals
Docker didn't invent process isolation — cgroups and namespaces already existed in the Linux kernel. What it added was a packaging format: images, layers, and a registry protocol that made "it works on my machine" solvable by shipping the machine along with the code. This guide covers images, containers, layers, networking, and volumes in the order you'll actually hit them.
What Is Docker?
Docker is a platform for packaging an application together with everything it needs to run, and executing that package as an isolated process on any machine that has Docker installed.
Before Docker, "it works on my machine" was a real engineering problem — an application's behavior depended on the exact OS, library versions, and configuration of the machine it ran on. Docker solves this by packaging the application, its dependencies, and its runtime environment into a single image that behaves identically everywhere: your laptop, a teammate's laptop, a CI runner, and a production server.
The core building blocks
Dockerfile
A text file with step-by-step instructions describing how to build an image — which base image to start from, what to install, what to copy in, and how to start the application.
Image
An immutable, versioned template produced by building a Dockerfile. Images are never modified once built — only new images are built.
Container
A running (or stopped) instance of an image. Many containers can be created from the same image, each isolated from the others.
Registry
A storage and distribution service for images (e.g. Docker Hub, a private registry, or a cloud provider's registry) — the mechanism by which images move between machines.
Visual Learning
Watch one Docker host handle images, layers, isolation, networking, volumes, configuration, compose stacks, lifecycle, failure recovery, and deployment as a single continuous system — not fifteen separate explanations.
Docker Architecture Diagram
Docker architecture, as this guide covers it, is a build-and-run pipeline, and the diagram under “What Is Docker?” above shows it end to end. A Dockerfile describes how to build an image, the image is stored in a registry so it can move between machines, and a container is a running instance created from that image. The rest of this guide covers each stage in detail, starting with images and layers.
Why Containers Exist
Containers solve two problems at once: environment consistency, and efficient use of hardware.
The consistency problem
Before containers, deploying software meant carefully replicating a server's exact configuration — OS version, installed packages, library versions, environment variables — by hand or with configuration management tools. Any drift between environments (dev, staging, prod) could cause bugs that only appeared in one place.
The efficiency problem
Virtual machines solved isolation by giving each application its own full operating system — but that means duplicating gigabytes of OS overhead and minutes of boot time per application. Running ten applications meant ten guest kernels, ten copies of system libraries, and ten multi-second boots.
- 01Docker packages an application and its dependencies into an immutable image.
- 02Containers are isolated processes, not virtual machines — they share the host kernel.
- 03This gives near-instant startup and much lower overhead than VMs, at a slightly lower isolation guarantee.
Containers vs Virtual Machines
A virtual machine virtualizes hardware and runs a full guest operating system; a container virtualizes the operating system and runs an isolated process.
A hypervisor (like VMware ESXi or KVM) presents each VM with virtual hardware — virtual CPU, virtual disk, virtual NIC — and the VM boots its own kernel on top of that virtual hardware, just like it would on a physical machine. This gives very strong isolation (a VM can run an entirely different OS from its host) at the cost of size and boot time.
A container, by contrast, is simply a process running on the host, isolated using namespaces (separate views of process IDs, network interfaces, mounts, hostname…) and cgroups (limits on CPU, memory, and I/O). There is no second kernel, no virtual hardware — just the host kernel enforcing boundaries around a normal process.
Namespaces
Kernel feature that gives a process its own isolated view of a global resource — PID namespace (own process tree), network namespace (own network stack), mount namespace (own filesystem view), and more.
cgroups (control groups)
Kernel feature that limits and accounts for the resources (CPU, memory, disk I/O) a group of processes can use — this is how Docker enforces --memory and --cpus limits.
Images & Layers
A Docker image is not one big blob — it's a stack of read-only layers, one per Dockerfile instruction, unioned together into a single filesystem view.
When Docker builds an image, each instruction in the Dockerfile (FROM, RUN, COPY, …) produces a new layer containing only the filesystem changes made by that instruction. Layers are content-addressed (identified by a hash of their contents) and can be shared across many images — if two images both start FROM node:20-slim, they literally share that base layer on disk.
Build cache
If an instruction and its inputs haven't changed since the last build, Docker reuses the cached layer instead of re-running the instruction — this is why rebuilding after a small source change can take seconds instead of minutes.
Union filesystem
The mechanism (e.g. overlay2) that presents multiple stacked layers as one coherent filesystem to the running container, while keeping each layer independently stored and cacheable. See Docker's OverlayFS storage driver docs.
Containers & Their Lifecycle
A container moves through a well-defined lifecycle: created, running, stopped, and eventually removed.
Created
The container's filesystem and configuration exist, but its main process hasn't started yet (docker create).
Running
The main process is executing (docker start / docker run). The container has its own writable layer on top of the image's read-only layers.
Stopped
The main process has exited, but the container (and its writable layer) still exists on disk — it can be started again without rebuilding.
Removed
The container and its writable layer are deleted entirely (docker rm). Anything written inside the container that wasn't persisted to a volume is gone.
Container Networking
Docker gives every container its own network namespace, and lets you connect containers together on private, user-defined networks.
Bridge network
The default network driver — a private virtual network shared by containers on the same host. On a user-defined bridge network, containers can resolve each other by container name through Docker's built-in DNS (the default bridge network only supports access by IP address).
Port publishing
Explicitly mapping a container's internal port to a port on the host (-p 8080:80) so traffic from outside the host can reach the container. Without publishing, a container is only reachable from other containers on the same network.
Volumes & Persistent Storage
By default, everything written inside a container's writable layer disappears when the container is removed. Volumes decouple data from the container's lifecycle.
A named volume is a storage area managed by Docker, independent of any particular container. When a container mounts a volume at a path (e.g. /var/lib/postgresql/data), reads and writes to that path go to the volume instead of the container's own filesystem. If the container is removed and a new one is started with the same volume mounted, the data is still there.
Named volumes
Managed by Docker, identified by name, portable across containers — the recommended default for persisting application data.
Bind mounts
Map a specific path on the host filesystem directly into the container — commonly used in local development to live-mount source code.
Environment Variables & Configuration
The same image should be deployable to development, staging, and production without being rebuilt — configuration differences are injected at container start time.
Environment variables (-e KEY=value, or an env file) are the standard mechanism for injecting configuration — database URLs, feature flags, API keys, log levels — into a container without baking them into the image. This keeps the image itself environment-agnostic and reusable.
- 01Docker packages an application into an immutable image, run as an isolated container process — not a virtual machine.
- 02Images are built from stacked, cacheable, read-only layers; only the writable top layer belongs to a specific container.
- 03Containers move through a lifecycle: created → running → stopped → removed — only volumes survive removal.
- 04Docker networks let containers reach each other by name without exposing everything to the outside world.
- 05The same image should be deployed everywhere; environment differences belong in injected configuration, never in the image itself.