How to Fix Docker Permission Denied Error: Complete Guide

Few errors frustrate a fresh Docker install as reliably as permission denied while trying to connect to the Docker daemon socket. You install Docker, the service looks healthy, and the moment you run docker ps without sudo the CLI is thrown back at you with a socket path and a permission complaint. Unlike a "connection refused" message — which means the daemon never answered — this error is an access-control rejection: the socket file exists, the daemon is listening on it, but your user account is not allowed to read and write to it.

That distinction narrows the search dramatically. The networking layer is fine and dockerd is reachable; the problem lives in the Unix permissions of /var/run/docker.sock and the groups your shell belongs to. The usual suspects are a user that was never added to the docker group, a group change that was never applied to the current session, a socket with the wrong owner or mode, a daemon that is not actually running, an SELinux or AppArmor policy denying access, or a rootless Docker setup whose environment variables are not exported. This guide walks through each cause and the exact commands to resolve it.

What is the Docker Permission Denied Error?

The Docker CLI talks to the daemon over a Unix domain socket, by default /var/run/docker.sock. On a standard installation that socket is owned by root:docker with mode 0660, meaning only root and members of the docker group can open it. When your user lacks both, the kernel refuses the connect() syscall and the CLI surfaces a message such as Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json": dial unix /var/run/docker.sock: connect: permission denied.

Because the failure happens at the socket layer, the error proves the socket file exists and the daemon is bound to it. You should not spend time on firewalls or DNS; those produce different messages. Instead, focus on the three things the kernel checks: the file ownership of the socket, the file mode, and the groups your current login session carries. A mismatch on any one of the three returns the same permission-denied string.

One subtlety worth remembering: group membership is evaluated per session. Adding your user to the docker group updates /etc/group, but shells that were already open — including the one you ran usermod from — keep their old group list until you log in again. This is why the most common "fix" appears to do nothing until the next login.

Common Causes

The permission-denied error traces back to a small, predictable set of root causes. Recognizing which one applies is usually faster than blindly retrying commands:

Step-by-Step Fix Guide

Step 1: Verify the Docker daemon is running

Before touching permissions, confirm the daemon is actually up. A stopped daemon can masquerade as a permission problem because the socket may be missing or stale. Check the service state with systemd:

sudo systemctl status docker
# If it is inactive or failed, start and enable it:
sudo systemctl start docker
sudo systemctl enable docker

If systemctl status reports active (running) and you still see the error, move on — the problem is permissions, not the daemon lifecycle.

Step 2: Add your user to the docker group

The canonical fix is to grant your account membership in the docker group, which owns the socket. Use usermod with the append (-aG) flags so you do not clobber your existing group list:

# Append the current user to the docker group
sudo usermod -aG docker $USER

# Verify the group exists and your user is listed
getent group docker
groups $USER

Note the security implication: any member of the docker group can gain root-equivalent access by mounting the host filesystem in a container. On shared or multi-tenant hosts, prefer sudo docker or rootless Docker over the group.

Step 3: Apply the new group membership

Group changes do not affect already-running shells. Your current terminal still carries the old group set, so docker ps will keep failing until the membership is loaded. Either log out completely and back in, or use newgrp for an immediate in-shell switch:

# Option A: open a new shell with the docker group active
newgrp docker

# Option B: fully log out and log back in (most reliable)
# On a desktop, sign out of the session; on SSH, exit and reconnect.

# Confirm the group is now active in this session
id -nG

If id -nG lists docker, retry docker ps. In the overwhelming majority of cases the error disappears here.

Step 4: Inspect the Docker socket ownership and permissions

If the error persists after a clean re-login, the socket itself may have the wrong owner or mode. Inspect it directly — the expected state is root:docker with srw-rw---- (mode 0660):

ls -la /var/run/docker.sock
# Expected: srw-rw---- 1 root docker 0 ... /var/run/docker.sock

# Correct ownership if it is root:root or another group
sudo chown root:docker /var/run/docker.sock

# Correct the mode so the group can read and write
sudo chmod 660 /var/run/docker.sock

Avoid the temptation to chmod 777 the socket. World-writable access lets every local user control the daemon, which is effectively root on the host. Stick to 660 with the docker group.

Step 5: Restart Docker and confirm socket access

When the socket was created with wrong ownership — common after a manual dockerd start or a partial upgrade — the cleanest fix is to let systemd recreate it. Restart the service, then verify access without sudo:

# Recreate the socket with correct ownership
sudo systemctl restart docker

# Confirm the socket now looks right
ls -la /var/run/docker.sock

# Test access as your normal user
docker ps
docker info

If docker ps returns the container table without sudo, the permission problem is resolved. If it still fails, a mandatory-access-control layer is the likely culprit.

Step 6: Resolve SELinux, AppArmor, and rootless misconfigurations

On SELinux-enabled systems (RHEL, CentOS, Fedora), the Unix permissions can be correct yet SELinux still denies the connect. Test by temporarily putting SELinux in permissive mode; if the error clears, write a proper policy rather than leaving permissive mode on:

# Temporarily set SELinux to permissive to confirm the cause
sudo setenforce 0
docker ps   # if this works, SELinux was blocking

# Restore enforcing mode and investigate policy
sudo setenforce 1
sudo ausearch -m AVC -ts recent | grep docker
sudo aa-status   # check AppArmor on Ubuntu/Debian

For rootless Docker, the client must point at the per-user socket. Ensure the environment is exported in your shell profile, otherwise the CLI falls back to /var/run/docker.sock and fails:

# Rootless Docker: export the user socket path
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

# Start the rootless daemon if it is not running
systemctl --user start docker
systemctl --user enable docker

docker ps

Docker Diagnostic Commands

These commands form a complete diagnostic loop for the permission-denied error. Run them in order to pinpoint whether the failure is the daemon, the group, the socket, or a MAC policy:

# 1. Is the daemon running?
sudo systemctl status docker

# 2. Does the socket exist, and who owns it?
ls -la /var/run/docker.sock

# 3. Does the docker group exist, and who is in it?
getent group docker

# 4. What groups does the current session actually carry?
id -nG

# 5. Add the user and switch into the group for this shell
sudo usermod -aG docker $USER
newgrp docker

# 6. Restart the daemon to recreate the socket cleanly
sudo systemctl restart docker

# 7. Verify access without sudo
docker info
docker ps

The gap between getent group docker (what the system knows) and id -nG (what your session carries) is the single most revealing comparison. If getent lists your user but id -nG does not, you need a new login or newgrp — not another usermod.

Quick Reference Table

Symptom Cause Fix
permission denied on every docker command User not in the docker group sudo usermod -aG docker $USER, then re-login
Still denied right after usermod New group not applied to current session newgrp docker or log out and back in
Socket owned by root:root, mode 0600 Socket ownership or mode wrong sudo chown root:docker ...sock; sudo chmod 660 ...sock
"Cannot connect to the Docker daemon" + permission denied Daemon not running or socket stale sudo systemctl start docker
Denied on RHEL/Fedora despite correct Unix perms SELinux policy blocking socket access Test with sudo setenforce 0, then write a policy
Rootless docker denied on root socket DOCKER_HOST / XDG_RUNTIME_DIR unset Export the user socket path and start --user service

FAQ

Do I have to log out and back in after usermod -aG docker?

Yes, unless you use newgrp docker in the current shell. Group membership is read at login time and cached for the life of the session, so usermod updates /etc/group but does not change the groups of already-running shells. A full log out and back in is the most reliable fix; newgrp docker opens a subshell with the new group for a quick test without leaving your session.

Is it safe to chmod 777 the Docker socket?

No. Making /var/run/docker.sock world-writable lets every local user — including compromised or untrusted accounts — control the Docker daemon, which is equivalent to root on the host because a container can mount the root filesystem. Always prefer chmod 660 with the docker group, or run rootless Docker, over relaxing the socket mode.

Why do I still get permission denied after rebooting?

Three common reasons. First, your user was added to the docker group on a different machine or in a different session and the change never synced. Second, the socket is being recreated with the wrong ownership on each boot — check for a custom systemd override or a manually started dockerd. Third, SELinux or AppArmor may be enforcing a policy that survives reboots. Run ls -la /var/run/docker.sock and id -nG right after reboot to see the actual state.

Should I just run docker with sudo instead of joining the group?

On a personal development machine, the docker group is convenient and widely accepted. On a shared, production, or multi-tenant host, sudo docker is safer because it leaves an audit trail and avoids granting persistent root-equivalent access to every process you run. For the strongest isolation, use rootless Docker, which runs the daemon entirely under your user namespace with no privileged socket at all.

Conclusion

The Docker permission-denied error is a socket-layer access-control rejection, which is good news: it means the daemon is reachable and the fix lives entirely in Unix permissions and groups. Work through the three things the kernel checks — socket ownership, socket mode, and the groups your session carries — and the cause almost always reveals itself. Confirm the daemon is running, add your user to the docker group with usermod -aG, apply the membership with a fresh login or newgrp, inspect and correct the socket with ls -la and chmod 660, restart Docker to recreate the socket, and rule out SELinux, AppArmor, or rootless misconfiguration.

The most common mistake is running usermod and immediately retrying docker ps in the same shell. Group changes do not apply until the next login, so a quick newgrp docker or a clean re-login resolves the majority of cases in seconds. Keep the socket at 660 owned by root:docker, and reach for rootless Docker when you need stronger isolation than the shared group provides.

Related Guides