Overview
Symptom: running a Docker command as a non-root user returns an error like:
- got permission denied while trying to connect to the Docker socket at unix:///var/run/docker.sock
Root cause: your process cannot read/write the Docker UNIX socket. On Linux, the socket is usually owned by root and group docker. On macOS/Windows, Docker Desktop proxies to a daemon; contexts and integration may be misconfigured.
This guide gives fast fixes and deeper checks for Linux, macOS/Windows, WSL2, and CI.
Quickstart (Linux)
If Docker is installed and running, the most common fix is to add your user to the docker group.
# 1) Create group if missing (usually exists)
sudo groupadd -f docker
# 2) Add your user to the group
sudo usermod -aG docker "$USER"
# 3) Apply the new group to the current shell (or log out/in)
newgrp docker
# 4) Test
docker run --rm hello-world
Security note: members of the docker group effectively have root-level access on the host.
Minimal working example
Use this tiny script to verify access. It fails with the same socket error if permissions are wrong.
#!/usr/bin/env bash
set -euo pipefail
echo "Checking Docker daemon access..."
# Replace with another lightweight image if desired
docker run --rm hello-world
echo "OK: able to talk to Docker daemon."
Run: bash ./check_docker.sh
Where is the socket?
| Environment | Default socket/path |
|---|---|
| Linux (rootful) | /var/run/docker.sock |
| Linux (rootless) | /run/user/${UID}/docker.sock |
| macOS/Windows with Docker Desktop | Context named desktop-linux; Docker CLI proxies to VM |
| WSL2 | /var/run/docker.sock inside distro (provided by Docker Desktop) |
Step-by-step fixes
- Confirm Docker is running and locate the socket
- Linux:
- sudo systemctl status docker
- ls -l /var/run/docker.sock
- Expected: srw-rw---- 1 root docker ... /var/run/docker.sock
- If the file is missing, start Docker: sudo systemctl start docker
- Check your groups
id
id -nG | tr ' ' '\n' | grep -x docker || echo "You are not in group 'docker'"
getent group docker || echo "Group 'docker' missing"
- If not in docker, add as shown in Quickstart. Re-login or run newgrp docker.
- Test with sudo to isolate a permissions problem
sudo docker info >/dev/null && echo "Works with sudo"
- If it works with sudo, the daemon is healthy and the issue is user permissions.
- Check DOCKER_HOST and context
- A wrong environment variable or context can point to a socket you cannot access.
echo "DOCKER_HOST=${DOCKER_HOST-}"
docker context ls
- If DOCKER_HOST is set unexpectedly, unset it: unset DOCKER_HOST
- If you’re on Docker Desktop, switch to the desktop-linux context: docker context use desktop-linux
- Rootless Docker (Linux)
If you installed rootless Docker, the client must use the user-scoped socket.
# Start user service
systemctl --user start docker
# Ensure your environment points to the rootless socket
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
# Verify
docker info | grep -i rootless || true
- To persist DOCKER_HOST, add the export line to your shell profile.
- Inside containers (Docker-in-Docker or Docker-outside-of-Docker)
- To access the host daemon from a container, mount the socket and align permissions:
# On the host
GID=$(getent group docker | cut -d: -f3)
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
--group-add "$GID" \
alpine:3.20 sh -c 'apk add --no-cache docker-cli && docker version'
- Alternatively run the container as root: -u 0 (less safe).
- With SELinux enforced, you may need a relabel: add :Z to the bind mount.
- macOS and Windows (Docker Desktop)
- Ensure Docker Desktop is running.
- Verify context:
docker context use desktop-linux
docker run --rm hello-world
- If using WSL2, enable integration for your distro in Docker Desktop, then inside the distro:
# Inside WSL2 distribution
sudo groupadd -f docker
sudo usermod -aG docker "$USER"
# Restart the distro or: wsl --terminate <DistroName>
- System services and CI runners
If a systemd service or CI runner must use Docker without sudo, grant group membership or set supplementary groups:
# /etc/systemd/system/myjob.service
[Service]
User=ciuser
Group=ciuser
SupplementaryGroups=docker
Environment=DOCKER_HOST=unix:///var/run/docker.sock
Then reload and restart: sudo systemctl daemon-reload && sudo systemctl restart myjob
Pitfalls and safe practices
- Don’t chmod 666 /var/run/docker.sock. It grants world write to the daemon.
- Remember to re-login after usermod -aG. newgrp docker affects only the current shell.
- Multiple Docker installs (distro vs. official) can create conflicting sockets. Remove the unused one.
- On SELinux systems, mounting the socket into containers may be blocked without proper labels (:Z).
- Beware that docker group membership is effectively root. Grant minimally and audit regularly.
- If DOCKER_HOST points to a TCP endpoint, ensure TLS and credentials are correct.
Performance notes
- Using sudo vs. docker group does not change Docker’s runtime performance; it only affects how you invoke the client.
- Rootless Docker can have slightly higher overhead for networking and I/O due to user namespaces and slirp4netns.
- Heavy CI pipelines that bind-mount the Docker socket into many containers can serialize on the single daemon; prefer a shared builder (e.g., BuildKit) or parallelize across multiple runners.
- On WSL2, building from files on the Windows filesystem (NTFS) is slower. Keep source under the Linux filesystem (e.g., \wsl$ or the distro’s home) for faster builds.
Verification checklist
- Docker daemon is running (systemctl status docker or Docker Desktop up).
- The correct socket exists and is group docker, mode 660.
- Your user is in the docker group, or DOCKER_HOST is set for rootless.
- docker run --rm hello-world succeeds without sudo.
FAQ
Why does adding my user to docker fix it?
- The socket is owned by group docker with write permission. Membership grants access to the daemon API.
Is adding myself to docker safe?
- It grants root-equivalent control. Use only for trusted users and environments.
I still get denied after usermod -aG. Why?
- You must re-login or run newgrp docker so the new group applies to your session.
How do I use rootless Docker?
- Install and start the user service, then point DOCKER_HOST to unix:///run/user/UID/docker.sock.
Can I change the socket location?
- Yes by starting dockerd with a custom -H option, but ensure the client DOCKER_HOST matches and permissions are correct.