skip to content

What does `dockerd-rootless-setuptool.sh install` set up, and what must already be on the host for it to succeed?

level: middleimportance: nice to knowfreq 24%

answer

  1. Run by the user, not root
  2. Ships in an extras package
  3. Two mapping helper binaries must exist
  4. Ranges declared in two /etc files
  5. Lingering keeps it alive after logout

basics

~10 s

The script ships in docker-ce-rootless-extras and installs a per-user Docker Engine: a systemd user unit for dockerd and a socket under $XDG_RUNTIME_DIR. It requires the newuidmap tools and subordinate UID/GID ranges for the user.

solid answer

~40 s

`dockerd-rootless-setuptool.sh` comes from the **docker-ce-rootless-extras** package and is run as the unprivileged user, not with sudo. Its `install` subcommand checks prerequisites, then writes a **systemd user unit** so the daemon runs under `systemctl --user`, and prints how to reach the resulting endpoint — a socket under `$XDG_RUNTIME_DIR`, typically `/run/user/1000/docker.sock`, exposed either by exporting `DOCKER_HOST` or by using the `rootless` CLI context it creates. Two host-level prerequisites must exist first: the **newuidmap/newgidmap** binaries (the `uidmap` package) and **subordinate ID ranges** for the user in /etc/subuid and /etc/subgid — the script refuses if either is missing. Two more steps make it survive real use: `systemctl --user enable --now docker`, and `sudo loginctl enable-linger <user>` so the daemon keeps running when the user is not logged in.

code

bash · 7 lines
bash
sudo apt-get install -y uidmap docker-ce-rootless-extras
grep "^$USER:" /etc/subuid /etc/subgid
dockerd-rootless-setuptool.sh install
systemctl --user enable --now docker
sudo loginctl enable-linger "$USER"
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
docker version

go deeper

for a junior

Know that Docker can also be installed per-user rather than as one system service, and that the per-user engine has its own socket, so it does not see the system daemon's images.

for a middle

Explain the install path end to end: the extras package, running the tool as the user, the uidmap helpers and /etc/subuid ranges it checks, the systemd user unit it writes, and how the CLI is pointed at the new socket.

for a senior

Show the operational details that decide whether it survives: enabling the user unit, lingering for accounts that must run without a login, and diagnosing 'my containers vanished' as a wrong-daemon or torn-down-session problem.

for a principal

Own when a per-user engine is the right estate decision at all — which hosts and which teams get one, how accounts are provisioned with ID ranges up front, and what you give up in central manageability compared with one shared daemon.

### What the tool is Rootless mode lets an unprivileged user run their own Docker Engine instead of sharing the system-wide one. The install path for it is a shell script, `dockerd-rootless-setuptool.sh`, which the engine repositories ship in the **docker-ce-rootless-extras** package. It is run by the target user (`dockerd-rootless-setuptool.sh install`), *not* under sudo — running it as root is the most common way people get it wrong, because the whole point is to configure a daemon that belongs to that user's session. ### What it checks before it does anything The script front-loads a prerequisite check and fails with a clear message rather than half-installing: - **newuidmap and newgidmap.** These setuid helpers are what allow an unprivileged process to map more than one ID inside a user namespace. On Debian and Ubuntu they come from the `uidmap` package; on RPM distributions they are in the shadow-utils family. Without them there is no way to give the daemon a usable range of IDs. - **Subordinate ID ranges.** The user needs entries in **/etc/subuid** and **/etc/subgid** — a line like `alice:100000:65536` granting that user a block of subordinate IDs. Most distributions create these automatically when the account is made, but accounts created by configuration management or by an installer frequently have none, and the script stops there. - **A user session with systemd.** The generated unit is a *user* unit, so the tool expects a running user instance of systemd and `$XDG_RUNTIME_DIR` to be set. This is why running it over `sudo su - user` often fails where a real login session works. ### What it produces On success you get three things. 1. A **systemd user unit** for the daemon, managed with `systemctl --user start docker` — note the `--user`, which is the whole difference from the system-wide service. 2. An **API endpoint owned by that user**: a socket under `$XDG_RUNTIME_DIR`, in practice `/run/user/<uid>/docker.sock`. Nothing about /var/run/docker.sock changes; the two engines coexist and see completely separate images and containers, which surprises people who expect `docker images` to show what the system daemon has. 3. Instructions for pointing the CLI at it — either `export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock` or a CLI context named `rootless` that the tool creates for you. ### The two steps people forget **Enable the user unit**: `systemctl --user enable --now docker`. Without `enable`, the daemon does not come back when the user's session restarts. **Enable lingering**: `sudo loginctl enable-linger "$USER"`. By default a user's systemd instance — and everything under it — is torn down when their last session ends. For an interactive developer that is invisible; for a service account running an invoice-rendering worker it means the containers die the moment the SSH session closes and never start at boot. Lingering is the switch that makes a per-user daemon behave like a real service. It is also the single most common "it worked yesterday" report from a first rootless deployment. ### Uninstalling and coexistence The same script takes `uninstall`, which removes the user unit and stops the per-user daemon. Coexistence with the system daemon is normal and supported — the rootless engine has its own data directory under the user's home, so images pulled in one are invisible to the other, and disk usage is counted twice if you pull the same image in both. When someone reports "my image disappeared", check `DOCKER_HOST` and which context is active before checking anything else: they are almost certainly talking to the other daemon. ### Why an interviewer asks this This is not a screening question — plenty of strong engineers have never installed rootless mode. It is asked to see whether you understand that Docker's install story has more than one shape, and whether you reason about *prerequisites and lifetime* rather than pasting commands. A good answer names the uidmap tooling and the subuid/subgid ranges as the things that must exist first, the user-scoped systemd unit and per-user socket as what you get, and lingering as the difference between a demo and something that survives a logout.

  • A rootless engine works while the user is logged in but every container is gone after they disconnect. What is missing?
    Lingering. By default systemd tears down a user's instance, and everything running under it, when that user's last session ends — so the per-user dockerd stops with the session and never starts at boot. `sudo loginctl enable-linger <user>` keeps the user manager alive independently of login, which is what makes the setup behave like a service. Pair it with `systemctl --user enable docker` so the unit is actually wanted at startup.
  • After installing rootless Docker, `docker images` shows nothing even though the host has plenty of images. Why?
    You are talking to a different daemon. The rootless engine listens on its own socket under $XDG_RUNTIME_DIR and keeps its data under the user's home, entirely separate from the system daemon on /var/run/docker.sock. Check DOCKER_HOST and the active CLI context: whichever one is set decides which engine answers. Images are not shared between them, so the same image pulled in both is stored and counted twice.
  • Why does dockerd-rootless-setuptool.sh refuse to run when /etc/subuid has no entry for the user?
    A rootless daemon needs a block of subordinate UIDs and GIDs to hand out, and those blocks are declared per-user in /etc/subuid and /etc/subgid. Without an entry there is nothing for the newuidmap/newgidmap helpers to map, so the script stops up front rather than producing a daemon that cannot start containers. The fix is an administrator adding a range for the account before rerunning the tool.

saying these in an interview costs you the question

  • Runs the setup tool with sudo as root
  • Expects images to be shared with the system daemon
  • Skips loginctl enable-linger for a service account
  • Thinks no host-level prerequisites are needed
  • Forgets DOCKER_HOST still points at the system socket

context