Skip to main content
DevOps Insightsguides & answers

Docker · troubleshooting

permission denied while trying to connect to the Docker daemon socket

Your user cannot open the Docker daemon's socket, /var/run/docker.sock, which only root and members of the docker group can use. Add yourself to the group and start a new login session, or use rootless Docker. Never chmod the socket to 666: anyone who can use the socket can get root on the host.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 10 sections

Before you start

  • sudo access on the machine, to add a user to the docker group.
  • The ability to log out and back in, or to start a new shell, so a group change takes effect.
  • Agreement that this user should have root-level control of the host: docker group membership gives exactly that.

Run this first

step 1 of 4
ls -l /var/run/docker.sock

Look for srw-rw---- root docker. No such file means the daemon is not running, which is a different problem

Shows whether the socket exists and who may open it.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

Which daemon is the CLI using?

docker context ls && echo "$DOCKER_HOST"

Cause space

4 of 4 still possible

  • Your user is not in the docker groupCommon
  • You were added to the group, but this session predates itCommon
  • The CLI is pointed at a socket you cannot useOccasional
  • Earlier sudo use left ~/.docker owned by rootOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Check it with a tool

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    ls -l /var/run/docker.sock

    Shows whether the socket exists and who may open it.

    Look for srw-rw---- root docker. No such file means the daemon is not running, which is a different problem

  2. Step 2

    id -nG && getent group docker

    Compares what this session has with what /etc/group says.

    Look for docker missing from id -nG; whether your user is in getent's list tells cause one from cause two

  3. Step 3

    docker context ls && echo "$DOCKER_HOST"

    Confirms which daemon the CLI is talking to before you change anything.

    Look for The default context and an empty DOCKER_HOST, unless you meant otherwise

  4. Step 4

    systemctl is-active docker

    Rules out a stopped daemon, which produces a different error that people often confuse with this one.

    Look for active

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

Your user is not in the docker group

Common

A fresh Docker Engine install on Linux lets only root and the docker group use the socket. Until someone adds your user to the group, every docker command without sudo is refused.

Confirm

ls -l /var/run/docker.sock && getent group docker

Group docker on the socket, and your user name missing from the getent line

Fix

  • Decide whether this user should have root-level control of the host. If not, use rootless mode instead.
  • Add the user to the group, then start a new login session: log out and back in, or reboot a virtual machine. newgrp docker applies it to one new shell straight away.
  • Check with docker run hello-world, without sudo.
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
docker run hello-world

From Docker's Linux post-install steps. groupadd reports that the group already exists if the install created it, which is harmless. -a appends; without it usermod replaces your other groups.

You were added to the group, but this session predates it

Common

usermod -aG docker changes /etc/group, but running shells keep the group list they started with. Terminals, tmux sessions, SSH connections and IDE terminals opened before the change all still lack it.

Confirm

getent group docker && id -nG

Your user listed in the docker group by getent, while id -nG for this session does not include docker

Fix

  • Log out and back in. For SSH, disconnect and reconnect; for tmux or an IDE, restart the server process, not only the pane.
  • Or run newgrp docker to start a shell that has the group now.

The CLI is pointed at a socket you cannot use

Occasional

DOCKER_HOST or the current docker context names a different daemon: another user's rootless daemon, a socket mounted into a container with a different group id, or a path left over from Docker Desktop. The group fix does not apply to a socket owned by someone else.

Confirm

echo "DOCKER_HOST=$DOCKER_HOST" && docker context ls

The endpoint actually in use. unix:///var/run/docker.sock is the system daemon; a path under /run/user/<uid>/ is a rootless daemon belonging to that user

Fix

  • Point the CLI at the daemon you mean: docker context use default, or unset DOCKER_HOST.
  • Inside a container that mounts the host socket, the container's group id must match the socket's group id on the host. Compare stat -c %g /var/run/docker.sock inside and outside.

Earlier sudo use left ~/.docker owned by root

Occasional

Not the socket refusal itself but its usual companion after you fix it. Docker's post-install guide notes that running docker with sudo before joining the group can leave ~/.docker owned by root, which produces WARNING: Error loading config file: … permission denied.

Confirm

ls -ld ~/.docker

Owner root instead of your user

Fix

  • Give the directory back to your user, as Docker's guide shows. Removing ~/.docker also works but loses saved settings and logins.
sudo chown "$USER":"$USER" "$HOME/.docker" -R
sudo chmod g+rwx "$HOME/.docker" -R

The commands from Docker's Linux post-install steps.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

The docker command does not run containers itself. It sends requests to a background service, the Docker daemon, through a special file called a socket. On Linux only root and members of the docker group may open that socket. This error means your user is neither, or the change that adds you has not reached your current login session yet.

What the message says, by Docker version

Not reproduced here: this machine has no Docker. The messages are read from Docker's client source at the docker-v29.0.0 and v28.5.1 tags (client/request.go); the socket path is the default one. The ls line shows the default ownership the post-install guide relies on.

Command

docker ps
ls -l /var/run/docker.sock
id -nG

Output · as shown in Docker client source, client/request.go (docker-v29.0.0)

$ docker ps    # Docker 29 and later
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock

$ docker ps    # Docker 28 and earlier
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: <request>: dial unix /var/run/docker.sock: connect: permission denied

$ ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 <date> /var/run/docker.sock

$ id -nG
<user> adm sudo

How to read it

  • Docker 29 shortened the message and dropped the failed request from it. Up to Docker 28 the same refusal ends with dial unix /var/run/docker.sock: connect: permission denied, after the HTTP request that could not be sent. Both mean the same thing.
  • srw-rw---- with owner root and group docker means only root and the docker group may connect. The leading s marks a socket.
  • id -nG lists the groups your current session has. No docker in it is the whole cause.
  • A missing or stopped daemon gives a different message: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? up to Docker 28, and failed to connect to the docker API at …; check if the path is correct and if the daemon is running from Docker 29.

Words used on this page

Docker daemon (dockerd)
The background service that actually builds images and runs containers. The docker command is a client that talks to it.
Unix socket
A file-like endpoint, here /var/run/docker.sock, through which programs on the same machine talk to each other. Its file permissions decide who may connect.
docker group
A Linux group whose members may use the daemon's socket without sudo. Docker's documentation warns it grants root-level privileges.
Login session
Your shell and everything started from it. Group memberships are read when it starts, so a group added later is not seen until you log in again or run newgrp.
Rootless mode
Running the daemon as your own user instead of root, with its own socket under $XDG_RUNTIME_DIR. Containers then cannot gain more privilege than you have.
Docker context
A named daemon endpoint the CLI talks to. The current context, or DOCKER_HOST, decides which socket is used.
What is actually happening

The docker CLI is only a client. Every command becomes an API request to dockerd, which on Linux listens on the Unix socket /var/run/docker.sock by default. Before any request is sent, the kernel checks whether your process may open that socket, using its file permissions.

Docker creates the socket owned by root with group docker and mode 660, so root and docker-group members may connect and everyone else is refused. The client sees the refusal from the kernel and reports it; the daemon never received anything.

Docker's documentation is direct about what the group means: only trusted users should be allowed to control the daemon, because it can share host directories into containers without limit. Membership is not a convenience setting; it is equivalent to root.

Group membership is read when a login session starts. Running usermod -aG docker adds you in /etc/group, but the shell you are typing in still has the old list, so the error continues until you log in again or start a shell with the new group.

How to tell this is your problem
WhereWhat you see
docker CLI, Docker 29 and laterpermission denied while trying to connect to the docker API at unix:///var/run/docker.sock
docker CLI, Docker 28 and earlierpermission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
End of the Docker 28 messagedial unix /var/run/docker.sock: connect: permission denied
id -nGNo docker group in the current session's list

How to know it is actually fixed

  • docker run hello-world works without sudo and prints its greeting.
  • id -nG in a new session includes docker.
  • ls -l /var/run/docker.sock still shows srw-rw---- root docker, unchanged.

Stopping it happening again

  • Add users to the docker group as part of provisioning, and treat it like granting sudo in reviews.
  • Prefer rootless mode on shared machines and developer workstations where users should not have root.
  • In CI, run Docker steps in a runner set up for it rather than mounting the host socket into job containers.
  • Do not use sudo docker as a habit. It leaves root-owned files in your home directory and hides the real setup problem.

Security considerations

  • Docker's post-install guide warns that the docker group grants root-level privileges. Anyone who can use the socket can start a container that mounts the host's / and change anything on it, so add only people you would give sudo.
  • Never fix this with chmod 666 /var/run/docker.sock or chmod 777. That hands root on the host to every local user and every process, including compromised ones. The permission resets when the daemon restarts, so people repeat it and spread the habit.
  • Mounting /var/run/docker.sock into a container, as some CI and monitoring setups do, gives that container the same root-level control of the host.
  • Where users should not have root, use rootless mode: the daemon runs as the user, so containers cannot gain more privilege than that user has.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it