Troubleshooting

Permission denied while trying to connect to the Docker daemon socket

Your user cannot open /var/run/docker.sock. Add it to the docker group safely, fix snap, rootless Docker and CI runners — and why chmod 666 is wrong.

Published ~7 min read

This error means the Docker daemon is running, but your user is not allowed to open its socket, /var/run/docker.sock. The socket belongs to root and the docker group, so the fix is to add your user to that group and start a new login session. Membership of the docker group is equivalent to root on that machine, so on a shared server use rootless Docker instead — and never chmod 666 the socket.

quick fix
sudo usermod -aG docker $USER
# log out and back in (or run: newgrp docker), then
docker ps

The wording depends on the Docker version — Docker 29 and later say docker API, earlier releases say Docker daemon socket, and older ones start with Got permission denied — but the ending is always the same:

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

# earlier versions
permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sock: ... dial unix /var/run/docker.sock: connect: permission denied

If the shell says docker: command not found instead, Docker is not installed yet — see docker: command not found first. If it says the daemon may not be running, skip to that section; it is a different problem.

Why does Docker need permission at all?

The docker command is only a client. Everything happens in dockerd, a daemon that runs as root, and the client talks to it through a Unix socket. Whoever can write to that socket can ask a root process to start any container with any mounts — so access to it is restricted to root and one group:

check the socket and your groups
ls -l /var/run/docker.sock
# srw-rw---- 1 root docker 0 ... /var/run/docker.sock   (root:docker, mode 660)

id
# your groups — "docker" must be in the list

If the socket’s group is root rather than docker, the docker group is probably missing. Create it (below) and restart Docker with sudo systemctl restart docker.

How do I run docker without sudo?

Debian · Ubuntu · Rocky · Alma
# 1. the group normally exists already — the Docker packages create it
getent group docker || sudo groupadd docker

# 2. add your user to it (-a keeps your other groups)
sudo usermod -aG docker $USER

# 3. start a new login session — or, for this one shell only:
newgrp docker

# 4. test
docker run --rm hello-world
Alpine (as root)
addgroup <user> docker       # your account name, e.g. addgroup alice docker
rc-update add docker default
rc-service docker start

Do not drop the -a. usermod -G docker without it replaces all of the account’s supplementary groups — including sudo or wheel, which can lock you out of admin rights. If sudo itself is missing on a minimal image, see sudo: command not found.

Still denied after adding the group?

Group membership is read when a session starts. Every process that was already running keeps its old list of groups, so the change is invisible until you start fresh. Compare what the system knows with what your session has:

stale session or not?
getent group docker    # members on disk — your user should be listed
id -nG                  # groups of THIS session — "docker" missing = stale session

Listed in the first, missing from the second: log out completely and back in. The usual places an old session survives:

  • tmux or screen — the server process started before the change, and every new window inherits its groups. Detach, log out, log in, and start a new session (tmux kill-server ends all old ones).
  • SSH connection sharing — with ControlMaster in your SSH config, a new ssh reuses the old connection. Close it with ssh -O exit <host>, then reconnect.
  • VS Code Remote-SSH — its server keeps running on the host. Run “Remote-SSH: Kill VS Code Server on Host” from the command palette and reconnect.
  • A desktop session — log out of the graphical session entirely; closing the terminal is not enough.

newgrp docker is a shortcut that only fixes the one shell you run it in. A reboot also works, but it is never actually required.

Is Docker installed as a snap on Ubuntu?

If command -v docker prints /snap/bin/docker, Docker came from the snap store, which behaves differently: the snap does not create a docker group, and it can only reach files inside your home directory. The snap’s own README gives these steps for running it as a normal user:

Ubuntu · Docker snap
sudo addgroup --system docker
sudo adduser $USER docker
newgrp docker
sudo snap disable docker
sudo snap enable docker

On a server, Docker’s own apt repository is the better choice — current versions, the Compose plugin and no file-access confinement. Removing the snap also removes the containers and images it holds, so export anything you need first, then install as described in docker: command not found.

What is rootless Docker, and when should I use it?

Rootless mode runs the daemon as your own user, inside a user namespace, instead of as root. Access to that daemon’s socket is then worth exactly your own account’s rights, not root’s, which makes it the right answer on machines several people share. Each user gets their own daemon, images and containers.

Debian · Ubuntu · rootless
# log in as that user directly (SSH) — not via su or sudo -i
sudo apt install -y uidmap                  # newuidmap / newgidmap

# optional: stop the system-wide daemon if nobody needs it —
# this stops every container that daemon runs
sudo systemctl disable --now docker.service docker.socket

dockerd-rootless-setuptool.sh install       # ships with docker-ce-rootless-extras
sudo loginctl enable-linger $USER           # keep it running after you log out

docker context ls                           # the setup creates a "rootless" context
docker run --rm hello-world

Older versions print an export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock line instead of creating a context — add it to your shell profile. The setup needs a real login session with systemd, which is why su does not work. On Ubuntu 24.04 and later, AppArmor restricts unprivileged user namespaces, and Docker’s rootless documentation has the extra AppArmor step for it. Expect a few limits, such as no ports below 1024 by default. Podman is the other option: it runs rootless by default and accepts most docker commands.

Is it “Cannot connect to the Docker daemon” instead?

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? is not a permission problem. Docker 29 and later word the same situation as failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running. Either way, nothing answered on the socket: the daemon is stopped, failed to start, or the client is looking in the wrong place.

systemd · Debian · Ubuntu · Rocky · Alma
sudo systemctl status docker
sudo systemctl enable --now docker
sudo journalctl -u docker -n 50 --no-pager      # why it failed, if it did
Alpine · OpenRC (as root)
rc-update add docker default
rc-service docker start

If the daemon is running, the client may be pointed elsewhere:

wrong address
echo "$DOCKER_HOST"         # a leftover value overrides the default socket
unset DOCKER_HOST
docker context ls           # the * marks the active context
docker context use default

How do I fix it for Jenkins, GitLab Runner and other CI services?

Same cause, different user: the build runs as a service account. Add that account to the group, then restart the service — a running service keeps its old groups exactly like a login session does.

CI service accounts
# GitLab Runner (shell executor runs jobs as gitlab-runner)
sudo usermod -aG docker gitlab-runner
sudo systemctl restart gitlab-runner

# Jenkins
sudo usermod -aG docker jenkins
sudo systemctl restart jenkins

For a self-hosted GitHub Actions runner or any other agent, add whichever user its service runs as and restart that service. When a container mounts the socket itself (-v /var/run/docker.sock:/var/run/docker.sock) and runs as a non-root user, the group ID inside must match the host’s: --group-add $(getent group docker | cut -d: -f3). The same warning applies — mounting the socket hands that container the host.

Why is chmod 666 /var/run/docker.sock the wrong fix?

It makes the socket writable for every account and every process on the machine. A compromised web application, a cron job of another user, any local login — all of them can now start a privileged container, which is the same as handing each of them root. chown $USER /var/run/docker.sock is the same mistake, made for one account.

It does not even last. The socket is created again with root:docker and mode 660 whenever the daemon or docker.socket restarts, so the error comes back after the next reboot or package update. Use the group, or rootless mode. Note that this error is unrelated to a script’s Permission denied, which is about execute bits — see bash: Permission denied for that one.

Docker needs kernel features (namespaces, cgroups, overlay filesystems) that a KVM virtual machine controls itself and a container-based VPS often cannot offer; see KVM vs OpenVZ for the difference. Every VMHeaven KVM plan gives you that kernel and full root.

Frequently asked

Is adding my user to the docker group safe?

It is equivalent to giving that account root on the machine without a password prompt: anyone in the group can start a container that mounts the host filesystem. That is fine on a single-admin server or your own workstation. On machines several people share, use rootless Docker or Podman instead.

Do I need to reboot after usermod?

No. You need a new login session, because groups are read at login: log out and back in, or run 'newgrp docker' for the current shell. Long-running processes — a tmux server, the VS Code remote server, a CI service — keep their old groups until they are restarted.

Why does docker work with sudo but not without?

sudo runs the docker client as root, and root may open /var/run/docker.sock. The socket is owned by root:docker with mode 660, so your own user needs to be in the docker group — or you run a rootless daemon that belongs to your user.

What is rootless Docker?

A mode in which the Docker daemon runs as your own user inside a user namespace instead of as root, so access to its socket is worth only your account's rights. Set it up with 'dockerd-rootless-setuptool.sh install' after installing uidmap. It has some limits, such as no ports below 1024 by default.

Related articles

All troubleshooting