Fix "Cannot Connect to the Docker Daemon"
The daemon error almost never means Docker is broken. Nine times out of ten it's a stopped service, a stale context, or a wrong env var. Here's the checklist.
You run docker ps, expecting a list of containers, and instead get this:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock.
Is the docker daemon running?
I've hit this on fresh laptops, in CI runners, over SSH into boxes I'd forgotten I configured, and once on my own machine an hour after I'd installed Docker and walked away. The message reads like something is badly broken. It almost never is. The CLI is a thin client that talks to a daemon over a socket, and this error means the client couldn't reach that socket. That's it. Every fix below is about answering one question: which daemon should I be talking to, and is it up?
Work through these in order. The whole thing takes a couple of minutes and you'll usually be done by step two.
First, look at where the client is even pointing
Before touching services, check what the CLI thinks it should connect to. Two commands:
echo $DOCKER_HOST
docker context ls
If DOCKER_HOST is set to something you don't recognize (an old tcp:// address, a remote box that's long gone), that's your answer. I've seen this survive in a .bashrc from a tutorial someone followed two years ago. The CLI dutifully tries to reach a machine that no longer exists.
unset DOCKER_HOST
Then retry docker ps. If it works, go delete that export from your shell profile so it doesn't come back tomorrow.
docker context ls shows the same thing from the other side. The active context has a * next to it:
NAME DESCRIPTION DOCKER ENDPOINT
default * Current DOCKER_HOST based unix:///var/run/docker.sock
desktop-linux Docker Desktop unix:///home/me/.docker/desktop/docker.sock
If the star is on a context whose endpoint points somewhere unreachable, switch back:
docker context use default
This one bites people who install Docker Desktop and later install the native engine, or vice versa. The context gets left pointing at a socket that isn't being served anymore. docker context use is the whole fix.
Then check whether the daemon is actually running
On a Linux host with the native engine, the daemon runs as a systemd service. Ask systemd directly:
systemctl status docker
If you see Active: inactive (dead) or failed, start it:
sudo systemctl start docker
sudo systemctl enable docker # so it comes back after a reboot
I add the enable line because "it worked yesterday" after a reboot is the single most common way this error comes back. Fresh installs of the engine on some distros don't enable the service by default.
If the service refuses to start, it will loop in status. Don't guess at why. Read the logs:
journalctl -u docker --no-pager -n 40
The real cause is almost always in the last twenty lines. A corrupt daemon.json, a bad storage driver, a port already bound. I once spent ten minutes on a "mystery" that turned out to be a trailing comma in /etc/docker/daemon.json. The journal told me on line three; I just hadn't read it.
On Docker Desktop (Mac, Windows, or Linux), there's no systemd service to poke. The daemon lives inside Desktop's VM, and if Desktop isn't running, the socket isn't served. Open the app, wait for the whale icon to stop animating, then retry. Obvious, but it's caught me after a reboot more than once.
The socket is missing entirely
If ls -l /var/run/docker.sock returns "No such file or directory," no daemon has created it. That's the running-daemon problem above, not a separate bug. Start the service and the socket appears.
Permissions look like a connection error but aren't
There's a lookalike. If the daemon is up but your user isn't in the docker group, you get a permission-denied on the socket, which the CLI sometimes phrases close enough to the connection error to confuse you. Quick tell: sudo docker ps works but plain docker ps doesn't. If that's your situation, it's a group membership problem, and I've written up the Docker daemon permission fixes separately so I won't repeat them here.
Rootless and WSL2, the two setups that trip everyone
Rootless Docker doesn't use /var/run/docker.sock. It runs the daemon as your user, and the socket lives under your runtime dir:
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
systemctl --user status docker
Note the --user. Rootless is a user service, not a system one, so sudo systemctl will tell you nothing useful. If you set up rootless and then wonder why systemctl status docker says the unit doesn't exist, this is why.
WSL2 has its own trap. If you're running the Docker CLI inside a WSL2 distro and talking to Docker Desktop on Windows, that link is Desktop's WSL integration, and it's a per-distro toggle. Open Desktop, go to Settings, Resources, WSL Integration, and confirm your distro is switched on. When that toggle is off, the CLI inside WSL has no socket to reach and you get the exact daemon error. Flip it on, restart the shell.
The diagnosis flow, condensed
When I hit this cold, I run these four in a row before changing anything:
echo $DOCKER_HOST # is the client aimed somewhere weird?
docker context ls # is the active context sane?
systemctl status docker # is the daemon actually up? (or --user for rootless)
journalctl -u docker -n 40 # if it won't start, why not?
That sequence separates the "client is pointed wrong" cases (the first two) from the "daemon is down" cases (the last two), and those two families cover essentially every instance of this error I've seen.
The call we'd make
Don't reinstall Docker. I've watched people nuke a working install over this error when the actual problem was a stale DOCKER_HOST in their shell. Check where the client points, confirm the daemon is up, read the journal if it won't start. The error is loud and the fix is usually one line. Treat it as a routing question, not a broken-engine question, and you'll close it in under two minutes.
External Secrets Operator: One Secrets Workflow Across Clouds
We ran secrets three different ways across AWS, GCP, and Vault. External Secrets Operator gave us one Kubernetes-native workflow. Here's the setup and the gotchas.
GitHub Actions Best Practices in 2026: Workflows You Can Trust
A production-focused GitHub Actions guide: reusable workflows, least-privilege permissions, keyless OIDC to the cloud, SHA-pinned actions, environments with approvals, concurrency-safe deploys, and CodeQL/Dependabot gates — with copy-paste examples.
More from DevOps
Explore more articles in this category
GitHub Copilot CLI Sandboxing Is GA: What Actually Changed
GitHub made local sandboxing generally available for Copilot CLI on October 7, so the default now restricts the agent instead of trusting it.
The Tensorlake npm Compromise Targeted Your AI Tool Configs
A compromised npm release went after cloud credentials as expected, and local AI coding-assistant config files, which most teams never treated as secrets.
GitLab's New Rate Limits: What to Fix Before Oct 19
GitLab is capping unauthenticated API calls at 60 an hour starting October 19, and the preview windows land before most teams will have noticed.
You might have missed
Evergreen posts worth revisiting.