skip to content

After installing Docker Engine, `docker ps` fails with permission denied on /var/run/docker.sock — why, and what are the post-install steps?

level: juniorimportance: must knowfreq 76%

answer

  1. The CLI is only a client
  2. Something on /run must be opened
  3. A file with an owner and a group
  4. Group membership is fixed at login
  5. enable --now does two jobs at once

basics

~20 s

The docker CLI reaches dockerd through the unix socket /var/run/docker.sock, which is owned by root and group docker. Add your user with sudo usermod -aG docker $USER, then open a new login session so the group takes effect.

solid answer

~50 s

The `docker` command is only a client; it dials the unix socket **/var/run/docker.sock**, which the packages create as `root:docker` with mode 0660. A fresh install leaves your account outside the `docker` group, so the connect fails with *"permission denied while trying to connect to the Docker daemon socket"*. Fix it with `sudo usermod -aG docker $USER` and then start a **new** session — `newgrp docker`, or log out and back in — because supplementary groups are attached at login and your current shell will keep failing until then. The other half of the post-install work is the service: `sudo systemctl enable --now docker` both starts dockerd now and makes it start at boot. Distinguish the two failures by the message: *permission denied* means the socket exists but you cannot open it; *"Cannot connect to the Docker daemon… Is the docker daemon running?"* means dockerd is not up at all.

code

bash · 6 lines
bash
ls -l /var/run/docker.sock
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
newgrp docker
id -nG
docker version

go deeper

for a junior

Be ready to recite the post-install steps from memory: enable and start the daemon, add your user to the docker group, then open a new session. Know that docker version printing only a Client block means the daemon was never reached.

for a middle

Explain the mechanics: the CLI dials a unix socket owned root:docker with mode 0660, and supplementary groups are fixed when a session is created, which is why the same shell keeps failing after usermod.

for a senior

Show that you distinguish the two error strings instantly and go to the service state rather than guessing, and that you treat docker-group membership as a deliberate privilege grant on a shared host rather than a default.

for a principal

Own the policy question: who gets socket access on build and bastion hosts, whether that access is granted per-user or only to a service account, and how a new host is provisioned so nobody hand-runs usermod at all.

### The CLI is a client, not the engine Installing Docker Engine puts two very different things on the host. `docker` is a small client binary (packaged as `docker-ce-cli`) that speaks an HTTP API. `dockerd` is the long-running daemon (packaged as `docker-ce`) that actually builds images and starts containers. On Linux the default endpoint between them is the unix socket **/var/run/docker.sock** (usually a symlink to /run/docker.sock). Every failure in the first five minutes after an install is a failure to open or reach that socket, and the message tells you which. ### Failure one: the socket exists but you cannot open it The packages create the socket owned by `root`, group `docker`, mode 0660 — so only root and members of the `docker` group may open it. A normal user account is not in that group after a fresh install, and the client reports: ``` 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 ``` The documented post-install step is to create the group if it is absent and add yourself to it: ``` sudo groupadd docker # usually already created by the package sudo usermod -aG docker "$USER" ``` The part people get wrong is what happens next. Supplementary group memberships are baked into a process's credentials **when the session is created**; changing /etc/group does not retroactively change a shell that is already running, nor its children. So the very next `docker ps` in the same terminal still fails, and the candidate concludes the fix did not work. You must obtain a new session: log out and back in, open a fresh SSH connection, or run `newgrp docker` to spawn a subshell with the group applied. `id -nG` is the check — if `docker` is not in that output, the client will still be refused. Note the `-a` in `usermod -aG`. Without it, `usermod -G docker <user>` **replaces** the user's entire supplementary group list, which is a classic way to lock someone out of `sudo`. ### Failure two: nothing is listening The other message is different in kind: ``` Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? ``` That is the daemon being down. On a systemd host the engine ships `docker.service`, and the post-install step is: ``` sudo systemctl enable --now docker ``` `enable` writes the symlink that makes the unit start at boot; `--now` also starts it in this boot, so the two-command dance of `enable` plus `start` collapses into one. Doing only `start` is the common half-fix: everything works until the host reboots and the engine does not come back. Some distributions also ship `docker.socket` for socket activation, which is why the socket file can exist even when dockerd itself has never started. If `enable --now` fails, the engine is not the place to look first — read the unit's own output, because a daemon that refuses to start is nearly always a configuration or storage problem rather than a permissions one. ### Why the group and not sudo Candidates often propose "just use `sudo docker`" and stop there. It works, but it changes who owns files the daemon creates on bind mounts and it makes every shell alias and CI script carry sudo, so teams standardise on group membership for interactive users. It is worth knowing — and saying in an interview — that adding a user to the `docker` group is a privilege grant, not a convenience toggle: anyone who can open that socket can ask the daemon to run a container as root with the host filesystem attached. Treat it as an administrator-level decision on shared hosts rather than something you hand out by default. ### The checklist a candidate should be able to recite 1. `sudo systemctl enable --now docker` — daemon running now and after reboot. 2. `sudo usermod -aG docker "$USER"` — grant socket access. 3. New login session (or `newgrp docker`) — make the group real for your shell. 4. `docker version` — the honest smoke test, because it prints **both** a Client and a Server block. If only the Client block appears, the client never reached the daemon; the Server block appearing proves the socket, the group and the daemon are all fine. That last point is the one that separates a fluent answer from a memorised one: `docker run hello-world` proves the same thing but drags in registry access and image pulls, so it fails for reasons that have nothing to do with the install.

  • You ran usermod -aG docker and it still fails in the same terminal. What is happening?
    Supplementary groups are attached to a process when its session is created, so a shell that was already running never picks up the new membership, and neither do its children. You need a fresh login session — log out and back in, open a new SSH connection, or run `newgrp docker` for a subshell. `id -nG` confirms whether the running shell actually carries the group.
  • How do you tell a socket permission problem from a daemon that is not running, without looking at anything but the CLI output?
    Read the error. "Permission denied while trying to connect to the Docker daemon socket" means the socket file is there and your process may not open it — a group problem. "Cannot connect to the Docker daemon… Is the docker daemon running?" means nothing answered at that endpoint — a service problem. `docker version` also distinguishes them: it always prints the Client block, and prints a Server block only when the daemon actually replied.
  • Why is `sudo systemctl enable --now docker` preferred over `sudo systemctl start docker`?
    `start` only affects the current boot. `enable` creates the wants-symlink that makes the unit start automatically at boot, and `--now` starts it immediately as well, so one command covers both. Using only `start` produces the classic delayed failure: the host works fine for weeks and then comes back from a reboot with no engine running and every container gone from the process table.

Group membership is like a badge issued when you walk into the building: adding your name to the list at reception does nothing for the badge already clipped to your shirt — you have to leave and check in again.

saying these in an interview costs you the question

  • Says the fix needs no new login session
  • Claims docker ps failing always means the daemon is down
  • Runs usermod -G without -a, wiping other groups
  • Chmod 777 on /var/run/docker.sock as the fix
  • Uses systemctl start and never enable
  • Treats the docker group as a harmless convenience

context