docker-core-architecture
Quick Reference
Architecture Components
| Component |
Role |
Process |
| Docker CLI |
User-facing command interface |
docker |
| Docker Daemon |
API server, image management, orchestration |
dockerd |
| containerd |
Container runtime supervision, image pull/push |
containerd |
| runc |
OCI-compliant container spawner |
runc (exits after spawn) |
| BuildKit |
Image build engine (default since Engine 23+) |
buildkitd (within dockerd) |
Docker Object Types
| Object |
Description |
Key Command |
| Image |
Immutable, layered filesystem template |
docker build, docker pull |
| Container |
Runnable instance of an image with writable layer |
docker run, docker create |
| Network |
Isolated communication channel between containers |
docker network create |
| Volume |
Persistent storage managed by Docker |
docker volume create |
OCI Standards
| Standard |
Purpose |
Governs |
| OCI Image Spec |
Portable image format |
Layer format, manifest, config |
| OCI Runtime Spec |
Container execution contract |
Filesystem bundle, lifecycle, environment |
| OCI Distribution Spec |
Image registry API |
Pull, push, content discovery |
Critical Warnings
NEVER assume a container has persistent storage -- the writable container layer is deleted when the container is removed. ALWAYS use volumes or bind mounts for data that must survive container removal.
NEVER treat images as mutable -- images are immutable stacks of read-only layers. To change an image, ALWAYS build a new one. Using docker commit in production creates unreproducible, undocumented images.
NEVER send unnecessary files in the build context -- ALWAYS create a .dockerignore file. The entire build context directory is sent to the daemon before any build instruction executes.
NEVER confuse docker export/import with docker save/load -- export flattens all layers into a single filesystem tar (loses history and metadata). save preserves the full image structure with all layers, tags, and history.
NEVER run production workloads without resource limits -- containers without memory or CPU limits can consume all host resources. ALWAYS set -m and --cpus flags.
Architecture Diagram
Docker Architecture (Engine 24+)
+------------------+
| Docker CLI | User runs: docker build / run / pull / push
+--------+---------+
|
| REST API (Unix socket or TCP)
v
+--------+---------+
| Docker Daemon | dockerd
| | - Serves Docker API
| +------------+ | - Manages images, networks, volumes
| | BuildKit | | - Orchestrates container lifecycle
| +------------+ |
+--------+---------+
|
| gRPC API
v
+--------+---------+
| containerd | Container runtime supervisor
| | - Manages container lifecycle
| | - Pulls/pushes images (OCI compliant)
| | - Manages snapshots (layer storage)
+--------+---------+
|
| OCI Runtime Spec
v
+--------+---------+
| runc | OCI reference runtime
| | - Creates namespaces & cgroups
| | - Starts container process
| | - Exits after spawn (container runs independently)
+------------------+
|
v
+------------------+
| Container | Isolated process(es) with:
| | - Own PID, network, mount, UTS, IPC namespaces
| | - Resource limits via cgroups
| | - Union filesystem (read-only layers + writable layer)
+------------------+
Request Flow
- CLI sends REST API request to
dockerd (via Unix socket /var/run/docker.sock)
dockerd validates request, manages high-level logic (networking, volumes, images)
dockerd delegates container operations to containerd via gRPC
containerd prepares the OCI bundle (rootfs + config.json)
containerd calls runc to create and start the container
runc sets up namespaces, cgroups, and rootfs, then starts the process
runc exits -- the container process runs directly under containerd
Image and Layer Model
Union Filesystem
Docker images use a union filesystem (typically overlay2) that stacks read-only layers on top of each other:
Container (running)
+---------------------------+
| Writable Container Layer | <-- Changes (writes, deletes) go here
+---------------------------+
| Layer 4: COPY app.js | \
+---------------------------+ |
| Layer 3: RUN npm install | > Read-only image layers
+---------------------------+ |
| Layer 2: COPY package.json | |
+---------------------------+ |
| Layer 1: FROM node:20-slim | /
+---------------------------+
Key Layer Behaviors
- Each Dockerfile instruction that modifies the filesystem (RUN, COPY, ADD) creates one layer
- Layers are content-addressable -- identified by SHA256 digest of their contents
- Layers are shared across images -- if two images use the same base, the base layers exist only once on disk
- The writable container layer uses copy-on-write -- a file is copied from a lower layer to the writable layer only when modified
- Deleting a file in a higher layer creates a whiteout marker -- the file still exists in the lower layer but is hidden
- ALWAYS minimize layer count by combining related RUN commands with
&&
Image Identification
| Identifier |
Format |
Example |
| Repository + Tag |
name:tag |
nginx:1.25-alpine |
| Digest |
name@sha256:... |
nginx@sha256:a8560b... |
| Image ID |
Short SHA256 |
d1a364dc548d |
- Tags are mutable pointers --
nginx:latest can point to different images over time
- Digests are immutable -- ALWAYS use digests in production for reproducibility
- An image can have multiple tags pointing to the same digest
Build Context
The build context is the set of files sent to the Docker daemon when you run docker build.
How Build Context Works
- CLI packages the build context directory into a tar archive
- Tar archive is sent to the daemon (even if daemon is local)
- COPY and ADD instructions reference files relative to the build context root
- Files outside the build context are not accessible to the build
Build Context Rules
- The
. in docker build . specifies the build context directory
- The Dockerfile location (
-f) is independent of the build context
.dockerignore filters files BEFORE sending to the daemon
- ALWAYS exclude unnecessary files via
.dockerignore to reduce context size and build time
- Large contexts (>100MB) significantly slow down builds
Build Context Sources
| Source |
Example |
Notes |
| Local directory |
docker build . |
Most common |
| Git URL |
docker build https://github.com/user/repo.git |
Cloned by daemon |
| Tar archive |
docker build - < archive.tar.gz |
Extracted as context |
| stdin (Dockerfile only) |
docker build - <<< "FROM alpine" |
No file context available |
Container Lifecycle
State Diagram
docker create
|
v
+-----------+
| Created |
+-----------+
|
docker start
|
v
docker unpause +-----------+ docker pause
+--------------->| Running |<--------------+
| +-----------+ |
| | | |
| docker| |docker +--------+
| stop | | pause | Paused |
| | +-------------->+--------+
| v
| +-----------+
| | Stopped | (Exited)
| +-----------+
| |
| docker rm
| |
| v
| +-----------+
| | Removed |
| +-----------+
Lifecycle States
| State |
Description |
Key Behavior |
| Created |
Container exists but process has not started |
Writable layer allocated, config set |
| Running |
Main process is executing |
Has PID, consumes resources, network active |
| Paused |
Process suspended via cgroup freezer |
Memory preserved, CPU released, no I/O |
| Stopped |
Main process exited (exit code preserved) |
Writable layer preserved, no resource usage |
| Removed |
Container deleted |
Writable layer deleted, anonymous volumes removed if --rm |
Command-to-Architecture Mapping
| Command |
Docker Object Affected |
What Happens |
docker build |
Image |
BuildKit executes Dockerfile, produces layered image |
docker pull |
Image |
containerd fetches layers from registry via OCI Distribution |
docker run |
Container + (Image) |
Pull if needed, create container, allocate writable layer, start process |
docker create |
Container |
Allocate writable layer, set config, do NOT start |
docker start |
Container |
containerd calls runc to start process |
docker stop |
Container |
Send SIGTERM, wait grace period, then SIGKILL |
docker kill |
Container |
Send signal immediately (default SIGKILL) |
docker rm |
Container |
Remove writable layer and metadata |
docker rmi |
Image |
Remove image layers (if not referenced by other images/containers) |
Container Isolation Model
Docker containers are isolated using Linux kernel primitives:
Namespaces (What the container can see)
| Namespace |
Isolates |
Effect |
| PID |
Process IDs |
Container sees only its own processes; PID 1 is the main process |
| Network |
Network stack |
Own IP address, ports, routing table, firewall rules |
| Mount |
Filesystem |
Own root filesystem via union mount |
| UTS |
Hostname |
Own hostname and domain name |
| IPC |
Inter-process communication |
Own shared memory, semaphores, message queues |
| User |
UID/GID mapping |
Root inside container maps to unprivileged user on host (optional) |
Cgroups (What the container can use)
| Resource |
Control |
CLI Flag |
| Memory |
Hard limit, soft limit, swap |
-m 512m, --memory-swap 1g |
| CPU |
Share weight, core pinning, quota |
--cpus 1.5, --cpuset-cpus 0-3 |
| PIDs |
Maximum process count |
--pids-limit 200 |
| Block I/O |
Read/write bandwidth |
--device-read-bps /dev/sda:1mb |
Decision Trees
When to Use Which Docker Object
Need persistent data?
YES --> Use a Volume (docker volume create)
Shared between containers? --> Named volume
Single container temp data? --> tmpfs mount
Host file access needed? --> Bind mount
NO --> Container writable layer is sufficient
Need container communication?
YES --> Use a Network (docker network create)
Same host? --> User-defined bridge
Multi-host? --> Overlay (requires Swarm)
Direct LAN? --> Macvlan
NO --> Use --network none
Need a reusable environment?
YES --> Build an Image (Dockerfile + docker build)
NO --> Use docker run with existing image
Image vs Container Decision
Is it a template (immutable, shareable, versioned)?
--> IMAGE: Build it, tag it, push it
Is it a running instance (has state, has PID, consumes resources)?
--> CONTAINER: Run it, stop it, remove it
Reference Links
- references/concepts.md -- Docker object types, image layers, union filesystem details
- references/examples.md -- Architecture interaction examples, component diagrams
- references/anti-patterns.md -- Architectural mistakes and corrections
Official Sources
1---2name: docker-core-architecture3description: Use when designing Docker container architecture or explaining how Docker Engine components interact. Prevents misconceptions about container isolation, image layering, and the relationship between daemon, containerd, and runc. Covers Docker Engine architecture, OCI standards, image layers, container lifecycle, build context model, and Docker object types. Keywords: dockerd, containerd, runc, OCI, image layers, docker build, docker run, BuildKit, container lifecycle, how Docker works, what is a container, Docker internals, image vs container.4license: MIT5---67# docker-core-architecture89## Quick Reference1011### Architecture Components1213| Component | Role | Process |14|-----------|------|---------|15| Docker CLI | User-facing command interface | `docker` |16| Docker Daemon | API server, image management, orchestration | `dockerd` |17| containerd | Container runtime supervision, image pull/push | `containerd` |18| runc | OCI-compliant container spawner | `runc` (exits after spawn) |19| BuildKit | Image build engine (default since Engine 23+) | `buildkitd` (within dockerd) |2021### Docker Object Types2223| Object | Description | Key Command |24|--------|-------------|-------------|25| Image | Immutable, layered filesystem template | `docker build`, `docker pull` |26| Container | Runnable instance of an image with writable layer | `docker run`, `docker create` |27| Network | Isolated communication channel between containers | `docker network create` |28| Volume | Persistent storage managed by Docker | `docker volume create` |2930### OCI Standards3132| Standard | Purpose | Governs |33|----------|---------|---------|34| OCI Image Spec | Portable image format | Layer format, manifest, config |35| OCI Runtime Spec | Container execution contract | Filesystem bundle, lifecycle, environment |36| OCI Distribution Spec | Image registry API | Pull, push, content discovery |3738### Critical Warnings3940**NEVER** assume a container has persistent storage -- the writable container layer is deleted when the container is removed. ALWAYS use volumes or bind mounts for data that must survive container removal.4142**NEVER** treat images as mutable -- images are immutable stacks of read-only layers. To change an image, ALWAYS build a new one. Using `docker commit` in production creates unreproducible, undocumented images.4344**NEVER** send unnecessary files in the build context -- ALWAYS create a `.dockerignore` file. The entire build context directory is sent to the daemon before any build instruction executes.4546**NEVER** confuse `docker export`/`import` with `docker save`/`load` -- `export` flattens all layers into a single filesystem tar (loses history and metadata). `save` preserves the full image structure with all layers, tags, and history.4748**NEVER** run production workloads without resource limits -- containers without memory or CPU limits can consume all host resources. ALWAYS set `-m` and `--cpus` flags.4950---5152## Architecture Diagram5354```55 Docker Architecture (Engine 24+)5657 +------------------+58 | Docker CLI | User runs: docker build / run / pull / push59 +--------+---------+60 |61 | REST API (Unix socket or TCP)62 v63 +--------+---------+64 | Docker Daemon | dockerd65 | | - Serves Docker API66 | +------------+ | - Manages images, networks, volumes67 | | BuildKit | | - Orchestrates container lifecycle68 | +------------+ |69 +--------+---------+70 |71 | gRPC API72 v73 +--------+---------+74 | containerd | Container runtime supervisor75 | | - Manages container lifecycle76 | | - Pulls/pushes images (OCI compliant)77 | | - Manages snapshots (layer storage)78 +--------+---------+79 |80 | OCI Runtime Spec81 v82 +--------+---------+83 | runc | OCI reference runtime84 | | - Creates namespaces & cgroups85 | | - Starts container process86 | | - Exits after spawn (container runs independently)87 +------------------+8889 |90 v91 +------------------+92 | Container | Isolated process(es) with:93 | | - Own PID, network, mount, UTS, IPC namespaces94 | | - Resource limits via cgroups95 | | - Union filesystem (read-only layers + writable layer)96 +------------------+97```9899### Request Flow1001011. CLI sends REST API request to `dockerd` (via Unix socket `/var/run/docker.sock`)1022. `dockerd` validates request, manages high-level logic (networking, volumes, images)1033. `dockerd` delegates container operations to `containerd` via gRPC1044. `containerd` prepares the OCI bundle (rootfs + config.json)1055. `containerd` calls `runc` to create and start the container1066. `runc` sets up namespaces, cgroups, and rootfs, then starts the process1077. `runc` exits -- the container process runs directly under `containerd`108109---110111## Image and Layer Model112113### Union Filesystem114115Docker images use a **union filesystem** (typically overlay2) that stacks read-only layers on top of each other:116117```118 Container (running)119 +---------------------------+120 | Writable Container Layer | <-- Changes (writes, deletes) go here121 +---------------------------+122 | Layer 4: COPY app.js | \123 +---------------------------+ |124 | Layer 3: RUN npm install | > Read-only image layers125 +---------------------------+ |126 | Layer 2: COPY package.json | |127 +---------------------------+ |128 | Layer 1: FROM node:20-slim | /129 +---------------------------+130```131132### Key Layer Behaviors133134- Each Dockerfile instruction that modifies the filesystem (RUN, COPY, ADD) creates one layer135- Layers are **content-addressable** -- identified by SHA256 digest of their contents136- Layers are **shared** across images -- if two images use the same base, the base layers exist only once on disk137- The writable container layer uses **copy-on-write** -- a file is copied from a lower layer to the writable layer only when modified138- Deleting a file in a higher layer creates a **whiteout marker** -- the file still exists in the lower layer but is hidden139- ALWAYS minimize layer count by combining related RUN commands with `&&`140141### Image Identification142143| Identifier | Format | Example |144|------------|--------|---------|145| Repository + Tag | `name:tag` | `nginx:1.25-alpine` |146| Digest | `name@sha256:...` | `nginx@sha256:a8560b...` |147| Image ID | Short SHA256 | `d1a364dc548d` |148149- Tags are **mutable** pointers -- `nginx:latest` can point to different images over time150- Digests are **immutable** -- ALWAYS use digests in production for reproducibility151- An image can have multiple tags pointing to the same digest152153---154155## Build Context156157The **build context** is the set of files sent to the Docker daemon when you run `docker build`.158159### How Build Context Works1601611. CLI packages the build context directory into a tar archive1622. Tar archive is sent to the daemon (even if daemon is local)1633. COPY and ADD instructions reference files relative to the build context root1644. Files outside the build context are **not accessible** to the build165166### Build Context Rules167168- The `.` in `docker build .` specifies the build context directory169- The Dockerfile location (`-f`) is independent of the build context170- `.dockerignore` filters files BEFORE sending to the daemon171- ALWAYS exclude unnecessary files via `.dockerignore` to reduce context size and build time172- Large contexts (>100MB) significantly slow down builds173174### Build Context Sources175176| Source | Example | Notes |177|--------|---------|-------|178| Local directory | `docker build .` | Most common |179| Git URL | `docker build https://github.com/user/repo.git` | Cloned by daemon |180| Tar archive | `docker build - < archive.tar.gz` | Extracted as context |181| stdin (Dockerfile only) | `docker build - <<< "FROM alpine"` | No file context available |182183---184185## Container Lifecycle186187### State Diagram188189```190 docker create191 |192 v193 +-----------+194 | Created |195 +-----------+196 |197 docker start198 |199 v200 docker unpause +-----------+ docker pause201 +--------------->| Running |<--------------+202 | +-----------+ |203 | | | |204 | docker| |docker +--------+205 | stop | | pause | Paused |206 | | +-------------->+--------+207 | v208 | +-----------+209 | | Stopped | (Exited)210 | +-----------+211 | |212 | docker rm213 | |214 | v215 | +-----------+216 | | Removed |217 | +-----------+218```219220### Lifecycle States221222| State | Description | Key Behavior |223|-------|-------------|--------------|224| Created | Container exists but process has not started | Writable layer allocated, config set |225| Running | Main process is executing | Has PID, consumes resources, network active |226| Paused | Process suspended via cgroup freezer | Memory preserved, CPU released, no I/O |227| Stopped | Main process exited (exit code preserved) | Writable layer preserved, no resource usage |228| Removed | Container deleted | Writable layer deleted, anonymous volumes removed if `--rm` |229230### Command-to-Architecture Mapping231232| Command | Docker Object Affected | What Happens |233|---------|----------------------|--------------|234| `docker build` | Image | BuildKit executes Dockerfile, produces layered image |235| `docker pull` | Image | containerd fetches layers from registry via OCI Distribution |236| `docker run` | Container + (Image) | Pull if needed, create container, allocate writable layer, start process |237| `docker create` | Container | Allocate writable layer, set config, do NOT start |238| `docker start` | Container | containerd calls runc to start process |239| `docker stop` | Container | Send SIGTERM, wait grace period, then SIGKILL |240| `docker kill` | Container | Send signal immediately (default SIGKILL) |241| `docker rm` | Container | Remove writable layer and metadata |242| `docker rmi` | Image | Remove image layers (if not referenced by other images/containers) |243244---245246## Container Isolation Model247248Docker containers are isolated using Linux kernel primitives:249250### Namespaces (What the container can see)251252| Namespace | Isolates | Effect |253|-----------|----------|--------|254| PID | Process IDs | Container sees only its own processes; PID 1 is the main process |255| Network | Network stack | Own IP address, ports, routing table, firewall rules |256| Mount | Filesystem | Own root filesystem via union mount |257| UTS | Hostname | Own hostname and domain name |258| IPC | Inter-process communication | Own shared memory, semaphores, message queues |259| User | UID/GID mapping | Root inside container maps to unprivileged user on host (optional) |260261### Cgroups (What the container can use)262263| Resource | Control | CLI Flag |264|----------|---------|----------|265| Memory | Hard limit, soft limit, swap | `-m 512m`, `--memory-swap 1g` |266| CPU | Share weight, core pinning, quota | `--cpus 1.5`, `--cpuset-cpus 0-3` |267| PIDs | Maximum process count | `--pids-limit 200` |268| Block I/O | Read/write bandwidth | `--device-read-bps /dev/sda:1mb` |269270---271272## Decision Trees273274### When to Use Which Docker Object275276```277Need persistent data?278 YES --> Use a Volume (docker volume create)279 Shared between containers? --> Named volume280 Single container temp data? --> tmpfs mount281 Host file access needed? --> Bind mount282 NO --> Container writable layer is sufficient283284Need container communication?285 YES --> Use a Network (docker network create)286 Same host? --> User-defined bridge287 Multi-host? --> Overlay (requires Swarm)288 Direct LAN? --> Macvlan289 NO --> Use --network none290291Need a reusable environment?292 YES --> Build an Image (Dockerfile + docker build)293 NO --> Use docker run with existing image294```295296### Image vs Container Decision297298```299Is it a template (immutable, shareable, versioned)?300 --> IMAGE: Build it, tag it, push it301302Is it a running instance (has state, has PID, consumes resources)?303 --> CONTAINER: Run it, stop it, remove it304```305306---307308## Reference Links309310- [references/concepts.md](references/concepts.md) -- Docker object types, image layers, union filesystem details311- [references/examples.md](references/examples.md) -- Architecture interaction examples, component diagrams312- [references/anti-patterns.md](references/anti-patterns.md) -- Architectural mistakes and corrections313314### Official Sources315316- https://docs.docker.com/get-started/docker-overview/317- https://docs.docker.com/engine/318- https://docs.docker.com/build/buildkit/319- https://docs.docker.com/engine/storage/320- https://docs.docker.com/engine/network/321- https://docs.docker.com/engine/security/322- https://opencontainers.org/