Docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock
Hi, it's BlueByte. When docker ps or docker build stops with Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, the Docker CLI is working fine — it just couldn't reach the background service (the daemon) it hands every command to. The symptom is any docker command failing instantly with that line, or its close cousin permission denied while trying to connect to the Docker daemon socket. We'll walk through what the socket is, the three reasons the CLI can't reach it, how to confirm which one you hit, fix each, and keep it from coming back.
What the message — and its permission-denied variant — is telling you
The docker command you type is only a client. It talks to a long-running daemon over a Unix socket at /var/run/docker.sock, and every build, run, or ps is really a request across that socket. Two error strings mean the request never landed:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sockThey look similar but point at different causes. The first means nothing answered — the daemon is down or the CLI is aimed at the wrong endpoint. The second means the daemon is up and answered, but the kernel refused you access to the socket file. Read which one you got before you change anything.
The three reasons the CLI can't reach the socket
Both variants come down to one of these:
- The daemon isn't running — the
dockerservice is stopped or failed, so the socket has no listener. - Your user isn't in the
dockergroup — the daemon is up, but the socket is owned byroot:dockerand your account can't open it, so you getpermission denied. - The CLI is pointed at the wrong endpoint — a Docker context or a stray
DOCKER_HOSTsends your commands to a remote or rootless socket that isn't there.
First, check whether the daemon is actually running
Don't guess — ask systemd:
sudo systemctl status docker● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled)
Active: inactive (dead) since Mon 2026-09-15 09:02:11 KSTActive: inactive (dead) or failed means the daemon is down — that's your Cannot connect. If it says active (running), the daemon is fine and your problem is permissions or the context, covered below.
Fix a stopped daemon: start it and enable it on boot
Start the service, then set it to come up automatically so a reboot doesn't strand you:
sudo systemctl start docker
sudo systemctl enable docker.serviceActive: active (running) since Mon 2026-09-15 09:05:40 KSTIf start fails, read the logs with journalctl -u docker --no-pager -n 50 — a bad /etc/docker/daemon.json is the usual reason the daemon won't come up.
Fix "permission denied": add your user to the docker group
If the daemon is running but you get permission denied, your account can't open the root-owned socket. Add yourself to the docker group, then reload your group membership:
sudo usermod -aG docker $USER
newgrp dockernewgrp docker applies the new group in the current shell without a full logout. One caveat worth stating plainly: the docker group grants root-level privileges — anyone in it can start a container that mounts the whole host, so only add trusted users.
Fix a CLI pointed at the wrong context or DOCKER_HOST
If the daemon is up and you're in the group but it still can't connect, the CLI may be aimed elsewhere. List the contexts and see which is active:
docker context lsNAME DESCRIPTION DOCKER ENDPOINT ERROR
default * unix:///var/run/docker.sock
remote tcp://10.0.0.9:2375The * marks the active context. If it's on a remote or rootless one that isn't reachable, switch back:
docker context use defaultAlso check for a leftover override — echo $DOCKER_HOST. If it prints a tcp:// or a rootless unix://.../docker.sock you didn't mean to set, unset DOCKER_HOST and try again.
A real case: docker works with sudo but not without
You install Docker, run docker ps, and get permission denied while trying to connect to the Docker daemon socket. sudo docker ps works, which tells you the daemon is running — only your user lacks access. Rather than prefixing every command with sudo, you run sudo usermod -aG docker $USER and newgrp docker. Now docker ps works with no sudo, because your shell finally carries the docker group and can open the socket.
Confirm the socket answers end to end
Prove the whole path works — client, socket, daemon:
docker run hello-worldHello from Docker!
This message shows that your installation appears to be working correctly.docker version is the quieter check: if it prints a Server section and not just a Client section, the CLI reached the daemon. A missing Server block means you're still not connected.
Keep it from coming back — and how this differs from "Error response from daemon"
Enable the service (systemctl enable docker.service) so it survives reboots, keep your everyday user in the docker group, and avoid setting DOCKER_HOST globally in your shell profile where it silently redirects every project. Finally, don't confuse this with docker: Error response from daemon: .... That message means the CLI did reach the daemon — the connection worked and the daemon rejected the specific request (a bad image name, a port conflict). If you see Error response from daemon, stop looking at the socket; the connection is fine and the problem is the command itself.
Related questions
sudo docker works but plain docker doesn't. Why?
The daemon is running — only your user can't open the socket. Add yourself to the docker group with sudo usermod -aG docker $USER, then run newgrp docker (or log out and back in). Don't keep using sudo for every command.
I added myself to the docker group but still get permission denied.
The new group membership isn't loaded into your current shell yet. Run newgrp docker to pick it up now, or log out and back in. Confirm with the groups command that docker is listed.
systemctl status shows active (running) but docker still can't connect.
The CLI is probably aimed at the wrong endpoint. Run docker context ls to see the active context and echo $DOCKER_HOST for a stray override; switch back with docker context use default or unset DOCKER_HOST.
Can't I just chmod 666 the socket to fix permission denied?
Don't. Making /var/run/docker.sock world-writable hands root-equivalent control to every user on the box, and the change is lost on the next daemon restart anyway. Use the docker group instead — that's the supported path.
How is this different from 'Error response from daemon'?
Cannot connect means the CLI never reached the daemon. Error response from daemon means it did reach the daemon, which then rejected the specific request — a bad image name or a port conflict. If you see that, the socket is fine; fix the command.
References
Haneul Seo
Infrastructure engineer · 10+ years running Linux fleets
More in this category
Git: fatal: detected dubious ownership in repository
Since the CVE-2022-24765 fix in Git 2.35.2, Git refuses to read a repository whose working tree or .git directory is owned by a different user than the one running the command. It shows up in containers, CI jobs, sudo sessions and shared drives. Fix the ownership if the repo should be yours, or add the exact path to safe.directory in your global config — never in the repo's own config, which Git ignores for this.
Kubernetes: Internal error occurred: failed calling webhook
An admission webhook sits in front of your write, the API server could not get an answer out of it, and failurePolicy: Fail turned that silence into a rejection. The tail of the message is the whole diagnosis: context deadline exceeded means the call went nowhere, no endpoints available means nothing is running, and an x509 line means the API server does not trust the webhook's certificate. Each has a different fix, and none of them is your manifest.
MySQL: ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
A statement waited the full innodb_lock_wait_timeout for a row lock another transaction is still holding, and gave up. sys.innodb_lock_waits names the blocking session and hands you the KILL statement, and a blocking_query of NULL means the blocker is idle on an open transaction. The detail most retry loops get wrong: by default only the timed-out statement is rolled back, so your transaction is still open and still holds every lock it took earlier.
Redis: MISCONF Redis is configured to save RDB snapshots, but it's currently unable to persist to disk
Reads keep working and every write is rejected, because the last background save failed and stop-writes-on-bgsave-error defaults to yes. The log names the real cause — no space, a dir the redis user can't write, a read-only mount at rename time, or fork failing with Cannot allocate memory. Fix the cause, run one BGSAVE, and writes come back on their own with no restart: rdb_last_bgsave_status flips from err to ok. Setting stop-writes-on-bgsave-error no restores writes instantly but leaves the snapshot broken, so treat it as a deliberate trade, not the fix.
Node.js: FATAL ERROR: Reached heap limit — JavaScript heap out of memory (exit 134)
The V8 heap has its own ceiling, derived from system memory and the Node release, and it is often far below the RAM you have; when a build or server reaches it, V8 aborts with FATAL ERROR: Reached heap limit and exit code 134. Read the real limit with v8.getHeapStatistics().heap_size_limit, then raise it with --max-old-space-size (in MiB) or NODE_OPTIONS for a large workload, size it below the cgroup limit inside containers, and use --heapsnapshot-near-heap-limit to catch a leak in a long-running process. Exit 137 with no FATAL ERROR line is a container kill, not this.
Docker: "exec format error" when the container starts — wrong-platform image, no emulator, or a script with no shebang
The container exits on its first instruction with exec format error — the kernel's ENOEXEC, meaning the file exists but cannot be executed here. In practice that is an image built on one CPU architecture (an Apple-silicon Mac produces linux/arm64) and run on another (an x86_64 server) with no QEMU handler registered in binfmt_misc, or an entrypoint script whose first line is not a shebang. uname -m, docker image inspect and ls /proc/sys/fs/binfmt_misc tell the causes apart; the fix is an explicit docker buildx build --platform (or a manifest list for both), QEMU registration or --platform when you mean to emulate, and a #!/bin/sh line for the script.