Running Minecraft in Rootless Mode under Docker 20.10.6

Rootless mode was introduced in Docker Engine v19.03 as an experimental feature for the first time. Rootless mode graduated from experimental in Docker Engine v20.10.

Rootless mode allows running the Docker daemon and containers as a non-root user to mitigate potential vulnerabilities in the daemon and the container runtime. The rootless mode does not require root privileges even during the installation of the Docker daemon, as long as the prerequisites are met.


How it works

Rootless mode executes the Docker daemon and containers inside a user namespace. This is very similar to userns-remap mode, except that with userns-remap mode, the daemon itself is running with root privileges, whereas in rootless mode, both the daemon and the container are running without root privileges.

Rootless mode does not use binaries with SETUID bits or file capabilities, except newuidmap and newgidmap, which are needed to allow multiple UIDs/GIDs to be used in the user namespace.

Pre-requisite

  • Google Cloud Platform
  • Ubuntu 20.04 LTS
sudo curl -sSL https://get.docker.com/ | sh
# Executing docker install script, commit: 7cae5f8b0decc17d6571f9f52eb840fbc13b2737
+ sudo -E sh -c apt-get update -qq >/dev/null
+ sudo -E sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq apt-transport-https ca-certificates curl >/dev/null
+ sudo -E sh -c curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | apt-key add -qq - >/dev/null
Warning: apt-key output should not be parsed (stdout is not a terminal)
+ sudo -E sh -c echo "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" > /etc/apt/sources.list.d/docker.list
+ sudo -E sh -c apt-get update -qq >/dev/null
+ [ -n  ]
+ sudo -E sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
+ [ -n 1 ]
+ sudo -E sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker-ce-rootless-extras >/dev/null
+ sudo -E sh -c docker version
Client: Docker Engine - Community
 Version:           20.10.6
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        370c289
 Built:             Fri Apr  9 22:47:17 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Server: Docker Engine - Community
 Engine:
  Version:          20.10.6
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       8728dd2
  Built:            Fri Apr  9 22:45:28 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.4
  GitCommit:        05f951a3781f4f2c1911b05e61c160e9c30eaa8e
 runc:
  Version:          1.0.0-rc93
  GitCommit:        12644e614e25b05da6fd08a38ffa0cfe1903fdec
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
================================================================================
To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:
    dockerd-rootless-setuptool.sh install
Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.
To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/
WARNING: Access to the remote API on a privileged Docker daemon is equivalent to root access on the host. Refer to the 'Docker daemon attack surface'
         documentation for details: https://docs.docker.com/go/attack-surface/

Ensure that you have newuidmap and newgidmap CLI installed on your host system. These commands are provided by the uidmap package on most distros.

sudo apt install uidmap
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  libnuma1
Use 'sudo apt autoremove' to remove it.
The following NEW packages will be installed:
  uidmap
0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded.
Need to get 26.3 kB of archives.
After this operation, 171 kB of additional disk space will be used.
Get:1 http://asia-south1.gce.archive.ubuntu.com/ubuntu focal-updates/universe amd64 uidmap amd64 1:4.8.1-1ubuntu5.20.04 [26.3 kB]
Fetched 26.3 kB in 1s (33.7 kB/s) 
Selecting previously unselected package uidmap.
(Reading database ... 63405 files and directories currently installed.)
Preparing to unpack .../uidmap_1%3a4.8.1-1ubuntu5.20.04_amd64.deb ...
Unpacking uidmap (1:4.8.1-1ubuntu5.20.04) ...
Setting up uidmap (1:4.8.1-1ubuntu5.20.04) ...
Processing triggers for man-db (2.9.1-1) ...

If you installed Docker 20.10 or later with RPM/DEB packages, you should have dockerd-rootless-setuptool.sh in /usr/bin.

Run dockerd-rootless-setuptool.sh install as a non-root user to set up the daemon:

dockerd-rootless-setuptool.sh install
[INFO] Creating /home/docker_captain_india/.config/systemd/user/docker.service
[INFO] starting systemd service docker.service
+ systemctl --user start docker.service
+ sleep 3
+ systemctl --user --no-pager --full status docker.service
● docker.service - Docker Application Container Engine (Rootless)
     Loaded: loaded (/home/docker_captain_india/.config/systemd/user/docker.service; disabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-04-17 07:17:32 UTC; 3s ago
       Docs: https://docs.docker.com/go/rootless/
   Main PID: 4360 (rootlesskit)
     CGroup: /user.slice/user-1001.slice/user@1001.service/docker.service
             ├─4360 rootlesskit --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /usr/bin/dockerd
-rootless.sh
             ├─4376 /proc/self/exe --net=slirp4netns --mtu=65520 --slirp4netns-sandbox=auto --slirp4netns-seccomp=auto --disable-host-loopback --port-driver=builtin --copy-up=/etc --copy-up=/run --propagation=rslave /usr/bin/dock
erd-rootless.sh
             ├─4391 slirp4netns --mtu 65520 -r 3 --disable-host-loopback --enable-sandbox --enable-seccomp 4376 tap0
             ├─4399 dockerd
             └─4414 containerd --config /run/user/1001/docker/containerd/containerd.toml --log-level info
Apr 17 07:17:32 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:32.518269518Z" level=warning msg="Your kernel does not support CPU realtime scheduler"
Apr 17 07:17:32 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:32.518280114Z" level=warning msg="Your kernel does not support cgroup blkio weight"
Apr 17 07:17:32 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:32.518289157Z" level=warning msg="Your kernel does not support cgroup blkio weight_device"
Apr 17 07:17:32 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:32.518523007Z" level=info msg="Loading containers: start."
Apr 17 07:17:32 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:32.820716510Z" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred 
IP address"
Apr 17 07:17:33 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:33.100263067Z" level=info msg="Loading containers: done."
Apr 17 07:17:33 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:33.115802490Z" level=warning msg="Not using native diff for overlay2, this may cause degraded performance for building images: running in a user namespac
e" storage-driver=overlay2
Apr 17 07:17:33 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:33.116190065Z" level=info msg="Docker daemon" commit=8728dd2 graphdriver(s)=overlay2 version=20.10.6
Apr 17 07:17:33 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:33.116364504Z" level=info msg="Daemon has completed initialization"
Apr 17 07:17:33 minecraft dockerd-rootless.sh[4399]: time="2021-04-17T07:17:33.163000086Z" level=info msg="API listen on /run/user/1001/docker.sock"
+ DOCKER_HOST=unix:///run/user/1001/docker.sock /usr/bin/docker version
Client: Docker Engine - Community
 Version:           20.10.6
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        370c289
 Built:             Fri Apr  9 22:47:17 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Server: Docker Engine - Community
 Engine:
  Version:          20.10.6
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       8728dd2
  Built:            Fri Apr  9 22:45:28 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.4
  GitCommit:        05f951a3781f4f2c1911b05e61c160e9c30eaa8e
 runc:
  Version:          1.0.0-rc93
  GitCommit:        12644e614e25b05da6fd08a38ffa0cfe1903fdec
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
+ systemctl --user enable docker.service
Created symlink /home/docker_captain_india/.config/systemd/user/default.target.wants/docker.service → /home/docker_captain_india/.config/systemd/user/docker.service.Created symlink /home/docker_captain_india/.config/systemd/user/default.target.wants/docker.service → /home/docker_captain_india/.config/systemd/user/docker.service.
[INFO] Installed docker.service successfully.
[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service`
[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger docker_captain_india`
[INFO] Creating CLI context "rootless"
Successfully created context "rootless"
[INFO] Make sure the following environment variables are set (or add them to ~/.bashrc):
export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix:///run/user/1001/docker.sock

If dockerd-rootless-setuptool.sh is not present, you may need to install the docker-ce-rootless-extras package manually, e.g.,

sudo apt-get install -y docker-ce-rootless-extras
Reading package lists... Done
Building dependency tree       
Reading state information... Done
docker-ce-rootless-extras is already the newest version (5:20.10.6~3-0~ubuntu-focal).
The following package was automatically installed and is no longer required:
  libnuma1
Use 'sudo apt autoremove' to remove it.
0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.

The systemd unit file is installed as ~/.config/systemd/user/docker.service.

Use systemctl --user to manage the lifecycle of the daemon:

$ systemctl --user start docker
$ systemctl --user enable docker

If you try to run Nginx container, you still might not be able to run it as normal user.

docker_captain_india@minecraft:~$ docker run -d -p 8080:80 nginx
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/create: dial unix /var/run/docker.sock: connect: permission
 denied.
See 'docker run --help'.

You need to specify either the socket path or the CLI context explicitly.

To specify the socket path using $DOCKER_HOST:

export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

Now you can successfully Nginx container without sudo or root user:

docker run -d -p 8080:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
f7ec5a41d630: Pull complete 
aa1efa14b3bf: Pull complete 
b78b95af9b17: Pull complete 
c7d6bca2b8dc: Pull complete 
cf16cd8e71e0: Pull complete 
0241c68333ef: Pull complete 
Digest: sha256:75a55d33ecc73c2a242450a9f1cc858499d468f077ea942867e662c247b5e412
Status: Downloaded newer image for nginx:latest
795702f7965de6141ade74add2ed3c7d3881ae79b15924d5e5a55154ad2a6732

To specify the CLI context using docker context:

docker context use rootless
rootless
Current context is now "rootless"
Warning: DOCKER_HOST environment variable overrides the active context. To use "rootless", either set the global --context flag, or unset DOCKER_HOST environment variable.

Let us run Minecraft in rootless mode:

docker run -d -p 25565:25565 -e EULA=true -e ONLINE_MODE=false -e DIFFICULTY=hard -e OPS=collabnix  -e MAX_PLAYERS=50 -e MOTD="welcome to Raina World" -v /tmp/minecraft_data:/data --name mc itzg/minecraft-server

References: