Docker's most-reported error is a connection failure between the CLI and the background service it drives:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Recent Docker CLI versions print the same condition with different wording, including the underlying socket error:
failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory
Both mean the same thing, and everything below applies to either. docker is only a client — the actual work is done by a daemon (dockerd) that the client reaches over a Unix socket. This message means the client went to that socket and found nothing listening.
On Linux, the usual fix is one command:
sudo systemctl start docker
On macOS or Windows, open Docker Desktop and wait for it to finish starting.
First: Is This a Connection Error or a Permission Error?
These two get conflated constantly, and the fixes do not overlap. Compare the message you actually got:
| Message | What it means | Fix |
|---|---|---|
Cannot connect to the Docker daemon at unix:///var/run/docker.sock | Nothing is listening on the socket | Start the daemon |
failed to connect to the docker API at unix:///var/run/docker.sock ... no such file or directory | Same as above, newer CLI wording | Start the daemon |
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock | The daemon is running; your user cannot open its socket | Fix group membership |
Got permission denied while trying to connect to the Docker daemon socket | Same as above, older CLI wording | Fix group membership |
If your message contains "permission denied", starting the daemon will change nothing — jump to the permissions section near the end.
Why This Happens
- The daemon is not running. Freshly installed, crashed, or never enabled at boot.
- The daemon is still starting. Docker Desktop in particular boots a Linux VM first; the CLI works only once that is up.
DOCKER_HOSTpoints somewhere else. A leftover environment variable overrides the default socket.- The wrong Docker context is selected. Contexts do the same thing as
DOCKER_HOST, persistently. - No daemon exists in this environment at all — the common WSL case.
Fix 1: Start the Daemon (Linux)
# Is it running?
sudo systemctl status docker
# Start it now, and on every boot
sudo systemctl enable --now docker
# Confirm
docker info
If it refuses to start, read why rather than retrying:
sudo journalctl -u docker -n 50 --no-pager
Two failures dominate that log. A malformed /etc/docker/daemon.json stops the daemon outright — validate it:
sudo cat /etc/docker/daemon.json | python3 -m json.tool
A full disk stops it too, since the daemon cannot write to its data root:
df -h /var/lib/docker
On distributions without systemd, start it directly:
sudo service docker start
Fix 2: Start Docker Desktop (macOS and Windows)
There is no systemctl here — the daemon lives inside a VM managed by Docker Desktop.
# macOS: launch it from the terminal
open -a Docker
Then wait. The whale icon in the menu bar or system tray animates while the VM boots, and every docker command fails until it settles. This is the single most common cause of the error on a Mac: running docker ps a second after launching Desktop.
Confirm when it is genuinely ready:
docker info
If Desktop starts and then immediately stops, reset it from Troubleshoot → Clean / Purge data, or check that virtualisation is enabled — on Windows that means WSL 2 or Hyper-V being available.
Fix 3: Clear a Stale DOCKER_HOST or Context
A leftover environment variable silently redirects every command:
echo $DOCKER_HOST
If it prints anything you did not set deliberately — a tcp:// address, an old Docker Machine socket — clear it:
unset DOCKER_HOST
Then remove the line that set it from ~/.bashrc, ~/.zshrc, or your shell profile, or it returns on the next login.
Contexts are the persistent version of the same problem:
docker context ls
The active context is marked with *. If it points at a remote or retired endpoint, switch back:
docker context use default
Fix 4: WSL
A WSL distribution has no Docker daemon of its own. You have two options.
Use Docker Desktop's daemon — in Docker Desktop, Settings → Resources → WSL Integration, enable your distro, then restart the WSL shell. The docker CLI inside WSL then talks to Desktop's daemon.
Or run Docker natively inside the distro, which suits a Desktop-free setup:
sudo apt update && sudo apt install docker.io -y
sudo service docker start
Note that WSL does not run systemd by default on older versions, so service is the reliable command there, and the daemon will not survive a restart of the distro unless you start it again.
Verify the Fix
docker info is the right check, because it exercises the full client-to-daemon path and prints server details only on success:
docker info
A working daemon reports both halves:
Client:
Version: 29.5.2
...
Server:
Containers: 3
Images: 12
Server Version: 29.5.2
If you see a Client: block and then the connection error again, the CLI is fine and the daemon is still unreachable. Then run an actual container:
docker run --rm hello-world
If the Message Says "permission denied"
The daemon is running and your user cannot open its socket, because /var/run/docker.sock is owned by root:docker. Check:
ls -la /var/run/docker.sock
The standard fix is to join the docker group:
sudo usermod -aG docker $USER
newgrp docker # or log out and back in
This grants root-equivalent access to the host. Any member of the
dockergroup can start a container that mounts/from the host and read or modify any file on the system, withoutsudoand without an audit trail. On a personal workstation that is usually an acceptable trade. On a shared or production host it is a privilege escalation path — prefer rootless Docker or a controlledsudorule instead.
Prevention
sudo systemctl enable dockeron any Linux box you use regularly, so a reboot does not cost you a debugging session.- Set Docker Desktop to start at login on macOS and Windows, and give it a moment before running commands in a script.
- Validate
daemon.jsonbefore restarting. A JSON typo is the most common cause of a daemon that will not come back up. - Scripts should check first.
docker info >/dev/null 2>&1 || { echo "Docker is not running"; exit 1; }produces a clear failure instead of a confusing one halfway through a build.