Docker Permission Denied on docker.sock: Fix It Without sudo
You type docker ps and get permission denied while trying to connect to the docker API at unix:///var/run/docker.sock. With sudo the same command works. Or the error shows up inside a container that has the socket mounte
You type docker ps and get permission denied while trying to connect to the docker API at unix:///var/run/docker.sock. With sudo the same command works. Or the error shows up inside a container that has the socket mounted, and adding the user to the docker group changes nothing.
This guide reproduces each version of the error on Ubuntu 24.04 with Docker Engine 29.9.3 and fixes it. Every command and output below comes from that lab run on November 5, 2026, with a normal user named alice.
You're not alone with this one. On Stack Overflow, How to fix Docker: Permission denied had 1,945,544 views on November 5, 2026, and Got permission denied while trying to connect to the Docker daemon socket had 962,590.
The short version:
- Your user can't open
/var/run/docker.sock, which is owned byroot:dockerwith mode660. Runsudo usermod -aG docker $USER, then log out and back in, or runnewgrp docker. A shell that was open beforeusermodkeeps failing. - If
usermodsays the group does not exist, runsudo groupadd docker, add the user, and restart the Docker daemon so it sets the group on the socket. - Inside a container, add the host's numeric group ID:
--group-add "$(stat -c %g /var/run/docker.sock)", orgroup_addin Compose. The group namedockerin the image usually has a different number. - Don't
chmod 666the socket. The docker group is root-equivalent, so only add trusted users, and put a socket proxy in front of apps that only read container state.
Why Docker says permission denied on docker.sock
The docker command is only a client. It talks to the Docker daemon, dockerd, through a Unix socket at /var/run/docker.sock. The daemon runs as root. Whoever can open that socket can tell it to do anything.
What the socket permissions mean
On a fresh install, the socket looks like this:
srw-rw---- 1 root docker 0 Nov 5 02:17 /var/run/docker.sock
Only root and members of the docker group can read and write it. In the lab, alice had groups=1001(alice), so the kernel refused the connection before Docker saw the request. sudo docker ps works because root owns the socket.
The two forms of the error
Docker CLI 29.9.3 prints a short message:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
Older clients print the full API call. Docker CLI 26.1.5 on Debian 13 showed:
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.45/containers/json": dial unix /var/run/docker.sock: connect: permission denied
Both mean the same thing, and docker compose fails the same way, because it uses the same socket.
Fix it on the host with the docker group
The fix in the Docker post-install guide is to add your user to the docker group:
sudo usermod -aG docker $USER
That alone doesn't fix the shell you're typing in. This is the step most people miss.
Start a new session or run newgrp
Linux reads your groups when you log in. A shell that started before usermod keeps the old list. In the lab, alice had a shell open, root ran usermod -aG docker alice, and the old shell still failed:
[old shell] $ id
uid=1001(alice) gid=1001(alice) groups=1001(alice)
[old shell] $ docker ps
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
newgrp docker started a subshell with the new group, and a fresh login (su - alice, the same as a new SSH session) had it too. Both could run docker ps.
newgrp only changes that one subshell. For every terminal and your desktop session, log out fully and log back in. The Docker guide adds that a virtual machine may need a restart. Check with id that docker is in the list before you try again. Ubuntu created the group with GID 996 here. The number differs from machine to machine.
usermod: group 'docker' does not exist
If the docker group is missing, the daemon has no group to give the socket. The lab removed the group and restarted the daemon to reproduce it. dockerd logged a warning and the socket fell back to root:root:
level=warning msg="could not change group /var/run/docker.sock to docker: group docker not found"
srw-rw---- 1 root root 0 Nov 5 02:18 /var/run/docker.sock
usermod then failed with usermod: group 'docker' does not exist and exit code 6. Create the group first:
sudo groupadd docker
sudo usermod -aG docker $USER
sudo systemctl restart docker
The restart matters. Right after groupadd the socket still belonged to root:root, and docker ps as alice was still denied. Once the daemon came back up it set the socket to root:docker, and docker ps worked.
Why chmod 666 and sudo everywhere are the wrong fix
Many answers suggest sudo chmod 666 /var/run/docker.sock. It does make the error go away, because every user on the machine can now open the socket.
chmod 666 hands root to every account
That is the problem. Any process on the host, including a compromised web app running as www-data, can now start a privileged container. The change doesn't even last. In the lab the socket showed srw-rw-rw- after chmod 666, and after a daemon restart it was back to srw-rw---- root docker. You end up with an insecure fix that disappears at the next daemon restart, so the error comes back.
The docker group is root too
Adding a user to the docker group is the supported fix, but it gives the same power in a controlled way. The Docker guide is blunt about it: "The docker group grants root-level privileges to the user." The Docker security docs explain why. A container can mount the host's / directory and change the host filesystem without any restriction.
So treat docker group membership like sudo access. Add the accounts you'd trust with root, and nobody else. If you want Docker without root on the host at all, look at rootless mode, where each user runs their own daemon.
Fix permission denied inside a container
The error often appears in containers that mount the socket: CI agents, Jenkins, Portainer, Traefik, dashboards. As long as the container runs as root it works. Once the image switches to a normal user, it fails.
The group name inside the image doesn't match
The kernel checks numeric IDs, not names. In the lab, the socket on the host belonged to GID 1002. A container running as user 1000 saw this:
$ docker run --rm --user 1000:1000 -v /var/run/docker.sock:/var/run/docker.sock docker:29.9.3-cli sh -c 'ls -ln /var/run/docker.sock && getent group docker'
srw-rw---- 1 0 1002 0 Nov 5 02:18 /var/run/docker.sock
docker:x:2375:
The docker:29.9.3-cli image has its own docker group with GID 2375. So --group-add docker adds group 2375, which doesn't own the socket, and docker ps still fails. That explains the Stack Overflow question where group permissions seem correct (347,311 views). Pass the host's number instead:
docker run --rm --user 1000:1000 \
--group-add "$(stat -c %g /var/run/docker.sock)" \
-v /var/run/docker.sock:/var/run/docker.sock \
docker:29.9.3-cli sh -c 'id && docker ps'
This printed uid=1000 gid=1000 groups=1000,1002 and the container list.
Set group_add in Docker Compose
In Compose, the same fix is group_add. Read the number from an environment variable, so the file works on hosts with different GIDs:
services:
ci-agent:
image: docker:29.9.3-cli
user: "1000:1000"
group_add:
- "${DOCKER_GID:?set DOCKER_GID to the GID of /var/run/docker.sock}"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: sleep infinity
Then write the value into .env next to the file:
echo "DOCKER_GID=$(stat -c %g /var/run/docker.sock)" > .env
docker compose up -d
Without .env, Compose stopped right away with required variable DOCKER_GID is missing a value, which beats a container that starts and then fails. With it, id inside ci-agent showed groups=1000,1002 and docker ps listed the containers.
Give containers less than the full socket
A container with the socket has root on your host, so group_add doesn't make it safer. It only lets a non-root process use that power. Mounting the socket with :ro doesn't limit the API either. Many apps, like Homepage or Uptime Kuma, only need to list containers. A socket proxy covers that case. Its README puts the risk plainly: "Giving access to your Docker socket could mean giving root access to your host, or even to your whole swarm".
Run docker-socket-proxy with read-only access
This Compose file puts tecnativa/docker-socket-proxy:v0.5.0 on an internal network. The app container runs as user 1000, has no socket mount and no group tricks, and talks to the proxy over TCP:
services:
socket-proxy:
image: tecnativa/docker-socket-proxy:v0.5.0
environment:
CONTAINERS: 1
POST: 0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket
client:
image: docker:29.9.3-cli
user: "1000:1000"
environment:
DOCKER_HOST: tcp://socket-proxy:2375
command: sleep infinity
networks:
- socket
networks:
socket:
internal: true
CONTAINERS: 1 allows the container endpoints, and POST: 0 allows only GET and HEAD requests. Don't publish port 2375 to the host.
What a 403 from the proxy means
From the client, docker ps listed both containers. Everything else was refused:
$ docker compose exec client docker run --rm docker:29.9.3-cli true
docker: Error response from daemon: <html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>
docker images failed the same way, because IMAGES was not enabled, and so did docker stop, because it's a POST. The proxy log shows each blocked call, such as "POST /v1.56/containers/create HTTP/1.1" with status 403. When an app behind the proxy fails with this error, find the API section in its log and enable only that variable.
Errors that look like permission denied but aren't
Two other messages show up in the same searches. They need different fixes.
failed to connect to the docker API, is the daemon running
With the daemon stopped, Docker 29.9.3 printed one long line. It starts with failed to connect to the docker API at unix:///var/run/docker.sock and ends like this:
check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory
Older clients say Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, a question with 3.3 million views. The key part is no such file or directory. The socket isn't there, so start the daemon with sudo systemctl start docker and check sudo systemctl status docker if it won't stay up.
A leftover DOCKER_HOST gives the same error with a different path. In the lab, DOCKER_HOST=unix:///run/user/1001/docker.sock, a rootless socket that didn't exist, made docker ps fail even though the system daemon was running. docker context ls warned that the variable overrides the active context. unset DOCKER_HOST fixed it.
WARNING: Error loading config file
If you ran sudo docker login or other sudo docker commands before, ~/.docker may belong to root. In the lab, docker ps as alice still worked but printed:
WARNING: Error loading config file: open /home/alice/.docker/config.json: permission denied
Docker ignores your config, including registry logins, until you take the folder back:
sudo chown -R "$USER":"$USER" "$HOME/.docker"
The warning was gone on the next run. For more permission errors, the Grafana and Prometheus volume guide covers bind mount ownership, which is a different problem from the socket.
FAQ
Running Docker without sudo
How do I run Docker commands without sudo?
Add your user to the docker group with sudo usermod -aG docker $USER, then log out and back in or run newgrp docker. Check with id that docker appears in your groups. If you'd rather not give your account root-equivalent access, use rootless mode instead.
Why does docker work with sudo but not without it?
The socket is owned by root:docker with mode 660. Root can always open it, so sudo docker works. Your user can only open it as a member of the docker group in the current session.
I added my user to the docker group. Why do I still get permission denied?
Your current shell still has the old group list. Open a new login session or run newgrp docker. If id shows the group and it still fails, check ls -l /var/run/docker.sock. A socket owned by root:root means the daemon started before the group existed, so restart it.
Security and containers
Is chmod 666 on docker.sock safe?
No. It lets every account and service on the host control Docker, which means root on the host. It also resets when the daemon restarts, so it doesn't even fix the problem for long.
Is adding a user to the docker group a security risk?
Yes, in the same way as giving that user sudo. The Docker docs state that the group grants root-level privileges. Only add trusted users, or use rootless mode.
How do I fix docker.sock permission denied in a container?
Run the container with the socket's numeric group: --group-add "$(stat -c %g /var/run/docker.sock)", or group_add in Compose. A group name like docker resolves inside the image and usually has the wrong number. If the app only reads container state, give it a socket proxy instead of the socket.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.



