What docker run Actually Does: Daemon, containerd, runc, Namespaces, cgroups
A container is a normal Linux process with isolation and limits. Follow one docker run from the CLI through dockerd and containerd to kernel namespaces.
On this page
“Containers are lightweight VMs” is the most common wrong sentence in infrastructure. It is wrong in ways that matter: for performance, for security and for debugging. Walk one docker run through the machine and the correct picture appears.
The three Docker components
- Client: the
dockerCLI. It does not run containers. It sends API requests. - Host (daemon):
dockerdlistens for API requests and manages images, containers, networks and volumes. - Registry: where images are stored. Docker Hub is the best known, and companies run private ones.
Follow one command
docker run -d --memory 256m -p 8080:80 nginx
- The CLI calls the daemon
The client sends an API request over a Unix socket to
dockerd. Nothing has started yet. - The image is resolved and pulled
If the
nginximage is not local, the daemon pulls it from the registry. An image is a stack of read-only layers, each a filesystem diff, identified by content digests. Layers already on disk are reused, which is why a second pull is fast. - The daemon delegates to containerd
dockerdhands lifecycle work tocontainerd, a separate daemon that manages images and container processes. Behind it sits an OCI-compliant runtime, typicallyrunc. - runc asks the kernel for isolation
runccreates the process with new namespaces and places it in a cgroup with your limits (--memory 256m). It sets up the root filesystem from the image layers plus a thin writable layer, then starts the container’s command. - Networking and port mapping
A virtual network interface is attached and port 8080 on the host is forwarded to port 80 in the container. The process is now running, and
pson the host will show it as an ordinary process.
The kernel does the real work
Because containers share the host kernel, isolation is weaker than a VM’s. A kernel vulnerability or a misconfigured privileged container can expose the host. Run as non-root, drop capabilities, avoid privileged mode, and treat the Docker socket as root access.
Why this model changes how you debug
| Symptom | What it usually means |
|---|---|
| Container exits immediately | The main process ended or crashed, containers live as long as PID 1 |
| Restarts with no error | OOM kill from a cgroup memory limit |
| Data gone after restart | Writes went to the ephemeral layer, not a volume |
| Works locally, fails in CI | Different base image layers, architecture or kernel features |
| Cannot reach the app | Port not published, or listening on 127.0.0.1 inside the container |
Do
Keep one main process per container, store state in volumes, set memory and CPU limits, and run as a non-root user.
Don't
Treat a container like a VM: SSH into it, install packages by hand, and rely on its writable layer. Rebuild the image instead.
Takeaway
Docker is an interface over Linux features. The CLI calls a daemon, the daemon pulls layers and delegates to containerd and runc, and the kernel isolates a plain process with namespaces and limits it with cgroups. Hold that model and containers stop being magic, and their failure modes become predictable.
Frequently asked questions
Is a container a lightweight virtual machine?
No. A virtual machine runs its own kernel on virtualized hardware. A container is an ordinary process on the host kernel, isolated using Linux namespaces and limited using cgroups. That is why containers start in milliseconds and share the host's kernel, which also means a kernel vulnerability affects all of them.
What do Linux namespaces do?
They give a process its own view of a system resource: process IDs, network interfaces, mount points, hostname, inter-process communication and user IDs. Inside its namespaces the container sees only its own processes and filesystem, even though they all run on the same kernel.
What do cgroups do?
Control groups limit and account for the resources a group of processes can use, such as CPU, memory and I/O. Namespaces decide what a container can see, cgroups decide how much it can use. Without cgroup limits, one container could consume all the host's memory.
Why is access to the Docker socket dangerous?
The Docker daemon usually runs as root, and its socket accepts commands to start containers. Anyone who can talk to it can launch a container that mounts the host filesystem, which is effectively root on the host. Never expose the socket to untrusted workloads.
/* Comments */
Comments are offline right now — we reconnect automatically, nothing is lost.