Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Theory: Docker architecture

Docker uses a client-server architecture. The tool you type commands into (the client) is separate from the process that actually runs containers (the daemon). They communicate over a REST API, which means the client and daemon do not have to be on the same machine.

Full architecture

flowchart TB
    subgraph DC["Docker Client"]
        CLI["docker CLI"]
    end
    subgraph DE["Docker Engine"]
        D["dockerd (Docker Daemon)"]
        C["containerd"]
        S["containerd-shim"]
        R["runc"]
    end
    REG[("Registry: Docker Hub / private")]
    K["Linux kernel: namespaces + cgroups"]

    CLI -->|"REST API"| D
    D <-->|"push / pull"| REG
    D --> C
    C --> S
    S --> R
    R --> K

Component roles

  • docker CLI is the client you type commands into. It sends requests to the daemon over a REST API, either on the same machine via a Unix socket or over the network.
  • dockerd (Docker daemon) receives those requests and manages images, containers, networks, and volumes. It exposes the Docker Engine API.
  • Registry stores and serves images. Docker Hub is the public default. Teams use private registries (AWS ECR, GitHub Container Registry, and others) to control who can push and pull. docker pull downloads from the registry; docker push uploads to it.
  • containerd handles the container lifecycle on behalf of the daemon. It pulls image layers, manages container state, and delegates process creation.
  • containerd-shim keeps each container process running independently from the daemon so a daemon restart does not kill running containers.
  • runc creates the container by calling into the Linux kernel. It sets up namespaces and cgroups and starts the application process.
  • Linux kernel enforces isolation (namespaces: what the process can see) and resource limits (cgroups: how much CPU and memory it can use).

What happens on docker run

  1. You type docker run. The CLI sends a request to dockerd via REST API.
  2. dockerd checks the local image store. If the image is not there it pulls it from the registry.
  3. dockerd calls containerd to create the container.
  4. containerd calls runc via a shim. runc asks the kernel to set up namespaces and cgroups, then starts your process.

What happens on docker build and push

docker build sends your Dockerfile and files to the daemon, which creates image layers and stores the result locally. docker push then uploads those layers to the registry so other machines can pull them.

Relevance to security

  • Misconfiguration can enter at the CLI (--privileged, volume mounts), in dockerd settings, or in daemon.json on the host.
  • The registry is on the trust path. Whoever controls push access to a registry can affect what every downstream host pulls and runs.
  • containerd and runc bugs have been part of past container escape incidents. Patching the host runtime matters as much as patching the app image.

Next: Lab: Dockerfile static analysis.