Practical Linux, Windows Server and cloud guides for IT pros.

Docker Permission Denied on Ubuntu: Socket, Group and Rootless Fixes

Fix Docker permission denied on Ubuntu by checking the socket, login groups, context and rootless service. Avoid exposing the daemon with chmod 666.

Filed under

, ,

Published

Written by

Last updated

Three checks for Docker permission errors: endpoint and socket, user groups and ownership, then rootful or rootless service.

A Docker permission error is not always a missing group membership. First read the path in the error. A failure opening /var/run/docker.sock, a warning about ~/.docker/config.json, and a denied image pull describe three different permission checks.

For a normal rootful Docker Engine installation on Ubuntu, the socket is commonly owned by root:docker with mode 660. A user outside that group cannot open it. Adding a trusted administrator to the group can fix that case, but it grants root-equivalent control of the machine. It is not a harmless convenience switch.

TL;DR

  • Identify the failing path before changing ownership or groups.
  • Confirm the daemon and context: sudo can silently point at a different installation.
  • Refresh the login session after an approved Docker group change.
  • Keep rootless Docker on its own user socket and service.
  • Never make the rootful socket world-writable.

Start here: run the read-only checks under Identify the endpoint. If Docker is not installed, start with the Ubuntu installation guide.

Error or symptomLikely boundaryFirst check
Permission denied on docker.sockUnix socket accessid; stat /var/run/docker.sock
Cannot connect to daemonEndpoint or daemon unavailabledocker context ls
Permission denied on config.jsonCLI configuration ownershipls -ld ~/.docker
Pull access deniedRegistry identity or image nameCheck registry and repository access
Works with sudo, wrong containers appearDifferent context/configurationCompare endpoints, not just success
Three checks for Docker permission errors: endpoint and socket, user groups and ownership, then rootful or rootless service.

Identify the endpoint before fixing permissions

command -v docker
docker --version
docker context show
docker context ls
id
printenv DOCKER_HOST DOCKER_CONTEXT DOCKER_CONFIG

An unset environment variable produces no output. Review the output locally: endpoints can disclose internal hostnames. An explicit --context, a context environment variable or DOCKER_HOST can redirect the client. The selected context alone is not proof that every command uses that endpoint.

docker context inspect --format '{{json .Endpoints.docker.Host}}' default
stat -c '%A %a %U %G %n' /var/run/docker.sock
systemctl is-active docker

These last checks apply to a local rootful Engine on a systemd-based Ubuntu host. Substitute the actual context name when inspecting a different context. A rootless installation or Docker Desktop may use another socket; do not create or change /var/run/docker.sock just because this example uses it.

A missing socket suggests a stopped service or wrong endpoint. An existing socket with a permission-denied error points towards access checks. A healthy local system service says nothing about a remote context. Keep those cases separate rather than restarting everything.

Fix rootful access only for a trusted administrator

On a machine you administer, and only when root-level Docker access is appropriate, inspect the configured group. Docker’s Linux post-installation guidance explicitly warns that Docker group membership grants root-level privileges.

getent group docker
id -nG

If the package created the group and you have approval to join it, append your current user. The -a matters: without append mode, changing supplementary groups can remove other memberships.

sudo usermod -aG docker "$USER"

Save your work, log out completely and log back in. Existing shells retain their old supplementary groups. An editor terminal launched by an older editor process can retain them too. Check id -nG in the exact terminal that failed, then run docker ps without sudo.

newgrp docker opens a group-enabled subshell and can help test the change, but it does not update every process in your desktop session. A full new login is easier to verify. Do not automatically add CI accounts, web-service users or every developer on a shared host.

Do not run chmod 666 /var/run/docker.sock. It allows any local user or process able to reach the socket to control a rootful daemon. A successful docker command after that change is not a secure fix.

To undo a membership you have just added, an administrator can remove that exact user from the Docker group with sudo gpasswd -d USERNAME docker. Replace USERNAME deliberately. Existing processes can retain access until their sessions end; removal is not an instant revocation of every running process.

Do not mix rootless Docker with the rootful socket

Rootless Docker runs the daemon as the user. Its socket is normally inside the user’s runtime directory, and its service belongs to the user service manager. Joining the rootful docker group is not the fix for a stopped rootless daemon. See Docker’s rootless prerequisites and setup before installing or migrating anything.

systemctl --user is-active docker
docker context ls
docker --context rootless info

The last command assumes a context actually named rootless exists. Use the name your setup created. If it is absent, inspect the installation rather than manufacturing a context pointing at a guessed socket. A rootless service can also depend on the user’s login lifecycle; service persistence should be configured intentionally.

Switching contexts does not move containers or images. Rootful, rootless and Desktop daemons have separate object stores. “My containers disappeared” after a switch usually means you are looking at another daemon. Record the previous context before changing it, and use an explicit --context while diagnosing.

Repair CLI configuration ownership without widening access

If the error names config.json, inspect the CLI configuration directory. Previous sudo commands can leave root-owned files in a user-owned directory. A custom DOCKER_CONFIG changes which directory is relevant.

ls -ld "$HOME/.docker"
ls -l "$HOME/.docker/config.json"

Only if these are your own normal configuration files, and you have confirmed that the path is not a shared directory or a symlink to another location, restore ownership of the affected files to your account. Keep authentication files private. Do not print config.json into a ticket: it may contain registry authentication data.

Avoid a recursive ownership change on a guessed path. Inspect the directory and fix the exact wrongly owned entries. If your organisation provisions shared Docker configuration, ask the owner before changing it. Ownership repair will not fix an expired registry token or grant access to a private image.

What the isolated lab reproduced

On 8 September 2026 I ran a fresh Docker-in-Docker lab, with no host socket, host bind mounts or published ports. The inner daemon used Docker 29.8.0 in Alpine userspace. This tested Linux socket behaviour; it was not a fresh Ubuntu installation or a rootless deployment test.

FixtureObserved resultMeaning
New user outside docker groupdocker ps failed with permission deniedDaemon existed, socket access was denied
Same user, new session after group additiondocker ps returned successfullyGroup access resolved this specific failure
Same user, nonexistent socket endpointdocker ps failed to connectGroup access cannot repair a wrong endpoint

The daemon stayed isolated throughout the test. The lab container and its anonymous volumes were removed afterwards. No existing workstation containers or data were changed. The contrast is the useful result: the same user can pass the group check and still fail because the client addresses the wrong socket.

Verify the fix and stop there

id -nG
docker context show
docker version
docker ps

Confirm the expected server identity and container list, not merely a zero exit code. Repeat the original operation from the original terminal or service account. If you changed a context, verify that deployment scripts still target the intended daemon.

If a plain docker ps works but a build or application still reports permission denied, read the new path. A bind-mounted directory, executable bit, registry or container UID has its own access rules. Do not keep adding host privileges after the daemon connection is already working.

Related: Docker command architecture and flags explains the client/daemon boundary; the Portainer home-lab guide builds on a working daemon connection.

Leave a Reply

Your email address will not be published. Required fields are marked *

Find more on the site

Keep reading by topic.

If this post was useful, the fastest way to keep going is to pick the topic you work in most often.

Want another useful post?

Browse the latest posts, or support TurboGeek if the site saves you time regularly.