BlueByte
Cannot connect to the Docker daemonFixed

Docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock

By Haneul SeoUpdated September 15, 20265 min

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.sock

They 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 docker service is stopped or failed, so the socket has no listener.
  • Your user isn't in the docker group — the daemon is up, but the socket is owned by root:docker and your account can't open it, so you get permission denied.
  • The CLI is pointed at the wrong endpoint — a Docker context or a stray DOCKER_HOST sends 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 KST

Active: 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.service
Active: active (running) since Mon 2026-09-15 09:05:40 KST

If 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 docker

newgrp 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 ls
NAME       DESCRIPTION   DOCKER ENDPOINT               ERROR
default *                unix:///var/run/docker.sock
remote                   tcp://10.0.0.9:2375

The * marks the active context. If it's on a remote or rootless one that isn't reachable, switch back:

docker context use default

Also 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-world
Hello 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

detected dubious ownershipFixed

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.

Git
failed calling webhookFixed

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.

Kubernetes
1205Fixed

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.

MySQL
MISCONFFixed

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.

Redis
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memoryFixed

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.

Node.js
exec /docker-entrypoint.sh: exec format errorFixed

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.

Docker