CertGrid CertGrid
Concepts·Docker

Rootless Docker and Daemon Socket Access

Membership of the docker group is equivalent to root on the host, and most people who have it do not know why. What the exposure actually is, what rootless mode changes, and what it costs you.

Security and Production Guide 39 of 46 Advanced

Inspected on the versions above. The rootless installation was NOT performed on the capture host - it makes host-wide changes to a shared machine. Only read-only inspection was executed; the install commands below are shown as reference and are labelled as such.

One Docker host is all this guide needs. Nothing here depends on a second machine, and the hardware above is modest on purpose - a 2 core, 4 GB VM runs everything in this path.
Server NameIP AddressOSRolesCPURAMHDD
DOCKER01192.168.0.21Ubuntu 26.04 LTSDocker Host2 Core4 GB50 GB

Before you start

  1. The daemon runs as root, and that is the whole issue

    Docker's daemon runs as root because creating namespaces, configuring networking and mounting filesystems all require it. The CLI talks to it over a Unix socket owned by root:docker. Anyone who can write to that socket can ask the daemon to do root things - which is why the group is not a lesser privilege.

    bash
    ls -l /var/run/docker.socksrw-rw---- 1 root docker 0 Aug 21 04:04 /var/run/docker.sock

    Expected resultA socket owned by root with group docker.

    Success conditionYou can see that the group is the access-control mechanism, and it grants access to a root-owned service.

  2. Why docker group means root

    This is not theoretical and it needs no exploit. Anyone who can talk to the daemon can ask it to mount the host's root filesystem into a container they control, as root. There is no permission boundary left after that. Treat granting docker group membership as granting root, because it is.

    bash
    # DO NOT RUN on a machine you do not own - this is the escalation, shown so you recognise itdocker run -v /:/host -it alpine chroot /host sh# the container now has a root shell on the HOST filesystemgetent group docker# audit who is in this group; each of them effectively has root

    Expected resultThe membership list. The escalation itself is deliberately not run here.

    Success conditionYou can justify treating docker group membership as a root grant in a security review.

  3. What rootless mode changes

    Rootless runs the daemon itself as your unprivileged user, inside a user namespace where your uid is mapped to root INSIDE the namespace but remains unprivileged outside it. A container escape lands the attacker as your ordinary user, not as host root. The daemon socket moves into your runtime directory and belongs to you alone.

    bash Example session
    docker info --format "{{json .SecurityOptions}}"["name=apparmor","name=seccomp,profile=builtin","name=cgroupns"]# a ROOTLESS daemon additionally reports name=rootless here

    Expected resultThe security options of the daemon you are talking to. This host is rootful, so rootless is absent.

    Success conditionYou can tell rootful from rootless with one command. That absent entry is the check.

  4. The tooling, and what installing it would do

    The setup tool ships with Docker on Ubuntu. It installs a systemd user service, sets up uid and gid mappings, and starts a second daemon owned by you - a host-level change affecting every user of the machine. It was deliberately not run here for that reason; the help output below is real, the installation is not something this guide performed.

    bash Example session
    dockerd-rootless-setuptool.sh --helpUsage: /usr/bin/dockerd-rootless-setuptool.sh [OPTIONS] COMMANDA setup tool for Rootless Docker (dockerd-rootless.sh).Documentation: https://docs.docker.com/go/rootless/Options:  -f, --force                Ignore rootful Docker (/var/run/docker.sock)Commands:  check        Check prerequisites# 'dockerd-rootless-setuptool.sh install' was NOT run - it changes a shared host

    Expected resultThe tool's own help. check reports prerequisites without changing anything.

    Success conditionYou know the tool exists and what installing it entails. Run check first on a machine that is yours.

  5. What rootless costs

    It is not free, and the limitations are the reason it is not the default. Binding ports below 1024 needs extra configuration. Some storage drivers and network features are unavailable. Performance through the userspace network stack is lower. Resource limits need cgroup v2 with delegation configured. For a developer workstation these rarely matter; for a production host they need checking against your requirements first.

    bash Example session
    docker info --format "cgroup={{.CgroupVersion}} driver={{.Driver}}"cgroup=2 driver=overlayfs

    Expected resultcgroup v2, which rootless needs for limits to work at all.

    Success conditionYou can list three things that would break before you migrate anything.

  6. What to do if you cannot go rootless

    Most of the benefit is available without switching daemons. Never mount the docker socket into a container - that hands the container the same root-equivalent access the group has. Run container processes as a non-root user. Drop capabilities. These are covered in the next guide and cost nothing.

    bash
    # mounting the socket gives that container root on the host - avoid it-v /var/run/docker.sock:/var/run/docker.sockdocker run --rm --user 1000:1000 alpine:3.22 iduid=1000 gid=1000 groups=1000

    Expected resultA container running as an unprivileged uid.

    Success conditionYou have a mitigation you can apply today. See guide 40 for the rest.

Troubleshooting

Official sources