Docker Daemon — The Engine Behind Every Docker Command
What Is the Docker Daemon in Simple Terms?
The Docker daemon (dockerd) is the background service that does all the actual work in Docker. When you type docker run nginx, the Docker CLI sends a request to the daemon. The daemon pulls the image, creates the container, sets up networking, and starts the process. The CLI is just a client that talks to the daemon.
Think of the daemon as a server that manages your container infrastructure. The CLI is the client that sends it commands. They communicate through a socket file on the host filesystem.
+------------------------------------------+| You type: docker run nginx |+------------------------------------------+ | REST API request POST /v1.43/containers/create | v+------------------------------------------+| dockerd (Docker Daemon) || || Receives the request || Checks: is nginx image local? || If not: pulls from Docker Hub || Creates container config || Calls containerd to start container || Sets up network and volumes || Returns container ID |+------------------------------------------+ | v+------------------------------------------+| containerd -> runc -> nginx process |+------------------------------------------+The Docker Socket — /var/run/docker.sock
The Docker CLI communicates with the daemon through a Unix socket at /var/run/docker.sock. This socket is the API endpoint for all Docker operations.
# The socket filels -la /var/run/docker.sock# srw-rw---- 1 root docker 0 Jan 15 09:00 /var/run/docker.sock# Only root and docker group members can use it # See the actual REST API calls your commands makecurl --unix-socket /var/run/docker.sock http://localhost/v1.43/containers/json# Returns JSON list of running containers — same as docker ps curl --unix-socket /var/run/docker.sock \ -X POST http://localhost/v1.43/containers/create \ -H 'Content-Type: application/json' \ -d '{"Image":"nginx"}'# Creates a container — same as docker create nginxDaemon Configuration
// /etc/docker/daemon.json — daemon configuration file{ "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "5" }, "storage-driver": "overlay2", "live-restore": true, "default-ulimits": { "nofile": { "Name": "nofile", "Hard": 64000, "Soft": 64000 } }, "features": { "buildkit": true }}# Manage the daemon with systemctlsudo systemctl status docker # Check if runningsudo systemctl start docker # Start the daemonsudo systemctl stop docker # Stop the daemonsudo systemctl restart docker # Restart (kills containers without live-restore)sudo systemctl reload docker # Reload config without restart # View daemon logssudo journalctl -u docker.service -f # Validate daemon configuration before applyingdockerd --validate# If valid: configuration OK# If not: shows the error in daemon.json # Daemon infodocker info# Shows: runtime, storage driver, logging driver, cgroup driver,# number of containers, images, CPU/memory availableThe Daemon's Relationship with containerd and runc
dockerd -> manages Docker API, images, networks, volumes | delegates container lifecycle to: vcontainerd -> manages container lifecycle (start, stop, pause) | creates OCI bundles, delegates execution to: vrunc -> creates Linux namespaces + cgroups, starts process exits immediately after container process startsThis three-layer architecture is why Kubernetes could deprecate Docker as a runtime while still running Docker images — Kubernetes speaks directly to containerd, bypassing dockerd entirely.
The Docker Socket Security Implications
# Anyone who can access the Docker socket has root on the host# Mounting the socket into a container gives that container root:docker run -v /var/run/docker.sock:/var/run/docker.sock alpine \ docker run --privileged --pid=host alpine nsenter -t 1 -m -u -n -i sh# This command gives you a root shell on the host from inside a container# NEVER mount the Docker socket in untrusted environments # Limit who can use Docker# Only add users to the docker group who genuinely need it:sudo usermod -aG docker trusted-engineer# The docker group = root equivalent — treat it that wayTroubleshooting Reference
| Problem | Symptom | Fix |
|---|---|---|
| Daemon not running | Cannot connect to the Docker daemon |
sudo systemctl start docker |
| Permission denied | Got permission denied while trying to connect |
Add user to docker group: sudo usermod -aG docker $USER then log out/in |
| Config file invalid | Daemon fails to start after editing daemon.json | dockerd --validate to check syntax |
| Containers die on daemon restart | No live-restore configured | Add "live-restore": true to daemon.json |
| Disk full | No space left on device |
docker system prune -f to clean unused objects |
PLACEMENT PRO TIP**Tip:** Add `"live-restore": true` to your daemon.json before you put any production workload on a Docker host. Without it, every daemon upgrade, restart, or crash kills all running containers. With it, containers keep running while the daemon restarts — zero downtime for daemon maintenance.
COMMON MISTAKE / WARNING**Security:** The Docker socket (`/var/run/docker.sock`) is equivalent to unrestricted root access on the host. Guard it accordingly. Never expose it over TCP without mutual TLS. Never mount it in containers you do not fully trust. Audit which users are in the `docker` group regularly — anyone in that group can escalate to root trivially.