Skip to content

Commit 89344f4

Browse files
AkihiroSudavvolandaevesdocker
authored
engine/security/rootless: split to multiple pages ; remove outdated/duplicated info (#23302)
<!--Delete sections as needed --> https://docs.docker.com/engine/security/rootless/ was too lengthy and giving a false sense that Rootless mode was quite clunky and hard to use, although actually it can be just set up in a single command: ``` dockerd-rootless-setuptool.sh install ``` ## Description <!-- Tell us what you did and why --> ### Commit 1: `engine/security/rootless: split to multiple pages` This commit only splits the page. The content will be updated in subsequent commits. ### Commit 2: `engine/security/rootless: remove outdated/duplicated info` Setup: - `dockerd-rootless-setuptool.sh` has been improved to show help when the prerequisites are not satisfied. Users no longer need to read the **lengthy** "prerequisites" documentation unless they encounter issues. - The document had duplicated descriptions about dbus, uidmap, and machinectl stuffs in several places. Graph drivers: - Rootless OverlayFS has been merged into the upstream since kernel 5.11: torvalds/linux@459c7c5 . Ubuntu no longer patches the kernel. - FUSE-OverlayFS is typically no longer needed on the current supported distros, except EL 8. SELinux: - Remove a workaround for an issue that was already fixed in Docker Engine v20.10.8. CLI: - `docker context use rootless` no longer needs to be executed manually, since Docker v23. (moby/moby#43061) ## Related issues or tickets <!-- Related issues, pull requests, or Jira tickets --> ## Reviews <!-- Notes for reviewers here --> <!-- List applicable reviews (optionally @tag reviewers) --> - [X] Technical review - [X] Editorial review - [ ] Product review ## Preview https://deploy-preview-23302--docsdocker.netlify.app/engine/security/rootless/ --------- Signed-off-by: Akihiro Suda <[email protected]> Co-authored-by: Paweł Gronowski <[email protected]> Co-authored-by: Allie Sadler <[email protected]>
1 parent 4cc42b2 commit 89344f4

File tree

3 files changed

+372
-364
lines changed

3 files changed

+372
-364
lines changed
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
---
2+
description: Run the Docker daemon as a non-root user (Rootless mode)
3+
keywords: security, namespaces, rootless
4+
title: Rootless mode
5+
weight: 10
6+
---
7+
8+
Rootless mode lets you run the Docker daemon and containers as a non-root
9+
user to mitigate potential vulnerabilities in the daemon and
10+
the container runtime.
11+
12+
Rootless mode does not require root privileges even during the installation of
13+
the Docker daemon, as long as the [prerequisites](#prerequisites) are met.
14+
15+
## How it works
16+
17+
Rootless mode executes the Docker daemon and containers inside a user namespace.
18+
This is similar to [`userns-remap` mode](../userns-remap.md), except that
19+
with `userns-remap` mode, the daemon itself is running with root privileges,
20+
whereas in rootless mode, both the daemon and the container are running without
21+
root privileges.
22+
23+
Rootless mode does not use binaries with `SETUID` bits or file capabilities,
24+
except `newuidmap` and `newgidmap`, which are needed to allow multiple
25+
UIDs/GIDs to be used in the user namespace.
26+
27+
28+
## Prerequisites
29+
30+
- You must install `newuidmap` and `newgidmap` on the host. These commands
31+
are provided by the `uidmap` package on most distributions.
32+
33+
- `/etc/subuid` and `/etc/subgid` should contain at least 65,536 subordinate
34+
UIDs/GIDs for the user. In the following example, the user `testuser` has
35+
65,536 subordinate UIDs/GIDs (231072-296607).
36+
37+
```console
38+
$ id -u
39+
1001
40+
$ whoami
41+
testuser
42+
$ grep ^$(whoami): /etc/subuid
43+
testuser:231072:65536
44+
$ grep ^$(whoami): /etc/subgid
45+
testuser:231072:65536
46+
```
47+
48+
The `dockerd-rootless-setuptool.sh install` script (see following) automatically shows help
49+
when the prerequisites are not satisfied.
50+
51+
## Install
52+
53+
> [!NOTE]
54+
>
55+
> If the system-wide Docker daemon is already running, consider disabling it:
56+
>```console
57+
>$ sudo systemctl disable --now docker.service docker.socket
58+
>$ sudo rm /var/run/docker.sock
59+
>```
60+
> Should you choose not to shut down the `docker` service and socket, you will need to use the `--force`
61+
> parameter in the next section. There are no known issues, but until you shutdown and disable you're
62+
> still running rootful Docker.
63+
64+
{{< tabs >}}
65+
{{< tab name="With packages (RPM/DEB)" >}}
66+
67+
If you installed Docker 20.10 or later with [RPM/DEB packages](/engine/install), you should have `dockerd-rootless-setuptool.sh` in `/usr/bin`.
68+
69+
Run `dockerd-rootless-setuptool.sh install` as a non-root user to set up the daemon:
70+
71+
```console
72+
$ dockerd-rootless-setuptool.sh install
73+
[INFO] Creating /home/testuser/.config/systemd/user/docker.service
74+
...
75+
[INFO] Installed docker.service successfully.
76+
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
77+
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger testuser`
78+
79+
[INFO] Creating CLI context "rootless"
80+
Successfully created context "rootless"
81+
[INFO] Using CLI context "rootless"
82+
Current context is now "rootless"
83+
84+
[INFO] Make sure the following environment variable(s) are set (or add them to ~/.bashrc):
85+
export PATH=/usr/bin:$PATH
86+
87+
[INFO] Some applications may require the following environment variable too:
88+
export DOCKER_HOST=unix:///run/user/1000/docker.sock
89+
```
90+
91+
If `dockerd-rootless-setuptool.sh` is not present, you may need to install the `docker-ce-rootless-extras` package manually, e.g.,
92+
93+
```console
94+
$ sudo apt-get install -y docker-ce-rootless-extras
95+
```
96+
97+
{{< /tab >}}
98+
{{< tab name="Without packages" >}}
99+
100+
If you do not have permission to run package managers like `apt-get` and `dnf`,
101+
consider using the installation script available at [https://get.docker.com/rootless](https://get.docker.com/rootless).
102+
Since static packages are not available for `s390x`, hence it is not supported for `s390x`.
103+
104+
```console
105+
$ curl -fsSL https://get.docker.com/rootless | sh
106+
...
107+
[INFO] Creating /home/testuser/.config/systemd/user/docker.service
108+
...
109+
[INFO] Installed docker.service successfully.
110+
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
111+
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger testuser`
112+
113+
[INFO] Creating CLI context "rootless"
114+
Successfully created context "rootless"
115+
[INFO] Using CLI context "rootless"
116+
Current context is now "rootless"
117+
118+
[INFO] Make sure the following environment variable(s) are set (or add them to ~/.bashrc):
119+
export PATH=/home/testuser/bin:$PATH
120+
121+
[INFO] Some applications may require the following environment variable too:
122+
export DOCKER_HOST=unix:///run/user/1000/docker.sock
123+
```
124+
125+
The binaries will be installed at `~/bin`.
126+
127+
{{< /tab >}}
128+
{{< /tabs >}}
129+
130+
Run `docker info` to confirm that the `docker` client is connecting to the Rootless daemon:
131+
```console
132+
$ docker info
133+
Client: Docker Engine - Community
134+
Version: 28.3.3
135+
Context: rootless
136+
...
137+
Server:
138+
...
139+
Security Options:
140+
seccomp
141+
Profile: builtin
142+
rootless
143+
cgroupns
144+
...
145+
```
146+
147+
See [Troubleshooting](./troubleshoot.md) if you faced an error.
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
---
2+
description: Tips for the Rootless mode
3+
keywords: security, namespaces, rootless
4+
title: Tips
5+
weight: 20
6+
---
7+
8+
## Advanced usage
9+
10+
### Daemon
11+
12+
{{< tabs >}}
13+
{{< tab name="With systemd (Highly recommended)" >}}
14+
15+
The systemd unit file is installed as `~/.config/systemd/user/docker.service`.
16+
17+
Use `systemctl --user` to manage the lifecycle of the daemon:
18+
19+
```console
20+
$ systemctl --user start docker
21+
```
22+
23+
To launch the daemon on system startup, enable the systemd service and lingering:
24+
25+
```console
26+
$ systemctl --user enable docker
27+
$ sudo loginctl enable-linger $(whoami)
28+
```
29+
30+
Starting Rootless Docker as a systemd-wide service (`/etc/systemd/system/docker.service`)
31+
is not supported, even with the `User=` directive.
32+
33+
{{< /tab >}}
34+
{{< tab name="Without systemd" >}}
35+
36+
To run the daemon directly without systemd, you need to run `dockerd-rootless.sh` instead of `dockerd`.
37+
38+
The following environment variables must be set:
39+
- `$HOME`: the home directory
40+
- `$XDG_RUNTIME_DIR`: an ephemeral directory that is only accessible by the expected user, e,g, `~/.docker/run`.
41+
The directory should be removed on every host shutdown.
42+
The directory can be on tmpfs, however, should not be under `/tmp`.
43+
Locating this directory under `/tmp` might be vulnerable to TOCTOU attack.
44+
45+
{{< /tab >}}
46+
{{< /tabs >}}
47+
48+
It's important to note that with directory paths:
49+
50+
- The socket path is set to `$XDG_RUNTIME_DIR/docker.sock` by default.
51+
`$XDG_RUNTIME_DIR` is typically set to `/run/user/$UID`.
52+
- The data dir is set to `~/.local/share/docker` by default.
53+
The data dir should not be on NFS.
54+
- The daemon config dir is set to `~/.config/docker` by default.
55+
This directory is different from `~/.docker` that is used by the client.
56+
57+
### Client
58+
59+
Since Docker Engine v23.0, `dockerd-rootless-setuptool.sh install` automatically configures
60+
the `docker` CLI to use the `rootless` context.
61+
62+
Prior to Docker Engine v23.0, a user had to specify either the socket path or the CLI context explicitly.
63+
64+
To specify the socket path using `$DOCKER_HOST`:
65+
66+
```console
67+
$ export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
68+
$ docker run -d -p 8080:80 nginx
69+
```
70+
71+
To specify the CLI context using `docker context`:
72+
73+
```console
74+
$ docker context use rootless
75+
rootless
76+
Current context is now "rootless"
77+
$ docker run -d -p 8080:80 nginx
78+
```
79+
80+
## Best practices
81+
82+
### Rootless Docker in Docker
83+
84+
To run Rootless Docker inside "rootful" Docker, use the `docker:<version>-dind-rootless`
85+
image instead of `docker:<version>-dind`.
86+
87+
```console
88+
$ docker run -d --name dind-rootless --privileged docker:25.0-dind-rootless
89+
```
90+
91+
The `docker:<version>-dind-rootless` image runs as a non-root user (UID 1000).
92+
However, `--privileged` is required for disabling seccomp, AppArmor, and mount
93+
masks.
94+
95+
### Expose Docker API socket through TCP
96+
97+
To expose the Docker API socket through TCP, you need to launch `dockerd-rootless.sh`
98+
with `DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp"`.
99+
100+
```console
101+
$ DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS="-p 0.0.0.0:2376:2376/tcp" \
102+
dockerd-rootless.sh \
103+
-H tcp://0.0.0.0:2376 \
104+
--tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem
105+
```
106+
107+
### Expose Docker API socket through SSH
108+
109+
To expose the Docker API socket through SSH, you need to make sure `$DOCKER_HOST`
110+
is set on the remote host.
111+
112+
```console
113+
$ ssh -l <REMOTEUSER> <REMOTEHOST> 'echo $DOCKER_HOST'
114+
unix:///run/user/1001/docker.sock
115+
$ docker -H ssh://<REMOTEUSER>@<REMOTEHOST> run ...
116+
```
117+
118+
### Routing ping packets
119+
120+
On some distributions, `ping` does not work by default.
121+
122+
Add `net.ipv4.ping_group_range = 0 2147483647` to `/etc/sysctl.conf` (or
123+
`/etc/sysctl.d`) and run `sudo sysctl --system` to allow using `ping`.
124+
125+
### Exposing privileged ports
126+
127+
To expose privileged ports (< 1024), set `CAP_NET_BIND_SERVICE` on `rootlesskit` binary and restart the daemon.
128+
129+
```console
130+
$ sudo setcap cap_net_bind_service=ep $(which rootlesskit)
131+
$ systemctl --user restart docker
132+
```
133+
134+
Or add `net.ipv4.ip_unprivileged_port_start=0` to `/etc/sysctl.conf` (or
135+
`/etc/sysctl.d`) and run `sudo sysctl --system`.
136+
137+
### Limiting resources
138+
139+
Limiting resources with cgroup-related `docker run` flags such as `--cpus`, `--memory`, `--pids-limit`
140+
is supported only when running with cgroup v2 and systemd.
141+
See [Changing cgroup version](/manuals/engine/containers/runmetrics.md) to enable cgroup v2.
142+
143+
If `docker info` shows `none` as `Cgroup Driver`, the conditions are not satisfied.
144+
When these conditions are not satisfied, rootless mode ignores the cgroup-related `docker run` flags.
145+
See [Limiting resources without cgroup](#limiting-resources-without-cgroup) for workarounds.
146+
147+
If `docker info` shows `systemd` as `Cgroup Driver`, the conditions are satisfied.
148+
However, typically, only `memory` and `pids` controllers are delegated to non-root users by default.
149+
150+
```console
151+
$ cat /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers
152+
memory pids
153+
```
154+
155+
To allow delegation of all controllers, you need to change the systemd configuration as follows:
156+
157+
```console
158+
# mkdir -p /etc/systemd/system/[email protected]
159+
# cat > /etc/systemd/system/[email protected]/delegate.conf << EOF
160+
[Service]
161+
Delegate=cpu cpuset io memory pids
162+
EOF
163+
# systemctl daemon-reload
164+
```
165+
166+
> [!NOTE]
167+
>
168+
> Delegating `cpuset` requires systemd 244 or later.
169+
170+
#### Limiting resources without cgroup
171+
172+
Even when cgroup is not available, you can still use the traditional `ulimit` and [`cpulimit`](https://github.com/opsengine/cpulimit),
173+
though they work in process-granularity rather than in container-granularity,
174+
and can be arbitrarily disabled by the container process.
175+
176+
For example:
177+
178+
- To limit CPU usage to 0.5 cores (similar to `docker run --cpus 0.5`):
179+
`docker run <IMAGE> cpulimit --limit=50 --include-children <COMMAND>`
180+
- To limit max VSZ to 64MiB (similar to `docker run --memory 64m`):
181+
`docker run <IMAGE> sh -c "ulimit -v 65536; <COMMAND>"`
182+
183+
- To limit max number of processes to 100 per namespaced UID 2000
184+
(similar to `docker run --pids-limit=100`):
185+
`docker run --user 2000 --ulimit nproc=100 <IMAGE> <COMMAND>`

0 commit comments

Comments
 (0)