Cloud Native Security. Chris Binnie
container's internal filesystem, which disabled a welcome security control. And, the avoid-at-all-costs Privileged mode was not possible in this setup either.
For rootless mode, however, the limitations are subtly different. In Table 2.1 we can see some of the limitations.
Table 2.1: Rootless Mode Limitations and Restrictions
RESTRICTED FUNCTIONALITY | DESCRIPTION/WORKAROUND |
---|---|
Control groups | Known as cgroups, these were used to throttle containers to quotas for host services such as CPU, I/O, and RAM but are not available in rootless mode. |
AppArmor | On Ubuntu derivatives or those OSs that use AppArmor, it is not possible to use the mandatory access controls in AppArmor. |
Checkpoint |
An experimental feature for snapshotting containers; checkpoints will not work in rootless mode: docs.docker.com/engine/reference/commandline/checkpoint .
|
Overlay v1 |
It appears that the original overlay storage driver is not compatible. Use overlay2 instead: docs.docker.com/storage/storagedriver/overlayfs-driver .
|
Privileged ports |
Sometimes known as root ports, privileged ports are any network ports below 1024 and for security reasons can only be exposed to the network by the root user. It is, however, possible to use the setcap command apparently to do this, but you should research the potentially unintended consequences: $ setcap cap_net_bind_service=ep $HOME/bin/rootlesskit .
|
Ping command |
On some Linux distributions it may not be possible to use the ping command without adding net.ipv4.ping_group_range = 0 2147483647 to the file /etc/sysctl.conf .
|
Networking |
You need to enter the correct namespace for the host to have visibility of the IP address of the container using nsenter (man7.org/linux/man-pages/man1/nsenter.1.html ), and the same applies to the host's networking as per user namespaces. The --net=host option won't work without extra effort or conceding security trade-offs.
|
The contents of Table 2.1 are not intended to put you off using rootless mode but instead give an insight into the lengths that the developers at Docker have had to go to in order to make this functionality a reality. There are unquestionably trade-offs, but that is almost always the case when security controls are introduced. You might have only one lock on the front door of your house, for example, but to be fully insurable your door probably needs two locks, which means paying for a second lock, fitting it, and carrying a second key with you when you have left the house.
Installing Rootless Mode
To get started we need to download an installation script as supplied by Docker. It can be found at get.docker.com/rootless
and, as with all online content, the script should be read through to check for any security implications that you do not want to be exposed to before applying it. And, having read the comments at the top of the script, you need to run a diff
command on the contents of the script github.com/docker/docker-install/blob/master/rootless-install.sh
before using the script at the other URL (choose the Raw option for the displayed format on GitHub for easy copying):
$ diff -y get-docker.sh install.sh
This Docker functionality is being actively developed, so if you have trouble with one version of the installation script, try the other, which might be a more stable version.
It should go without saying at this juncture that we do not need to be the root
user for the running containers. As a result, at this stage we will become the chris
user with this command:
$ sudo -i chris
Clearly, you should alter the username to suit your own needs, potentially using your nonprivileged login user.
We will run the slightly more stable get.docker.com
version of the script this way, saving it to install.sh
as a filename:
$ curl https://get.docker.com/rootless > install.sh
Now, make it executable and run the script:
$ chmod +x install.sh ; ./install.sh
After the short process is completed, you are greeted with Docker Engine client and server version information; for example, the client is installed as follows to match the server version:
Client: Docker Engine - Community Version: 19.03.12 API version: 1.40 Go version: go1.13.10
In Listing 2.1 we can see the tail end of the installation script's output.
Listing 2.1: Rootless Mode Docker Has Installed and Is Offering the User Information
# Docker binaries are installed in /home/chris/bin # WARN: dockerd is not in your current PATH or pointing to /home/chris/bin/dockerd # Make sure the following environment variables are set (or add them to ~/.bashrc): export PATH=/home/chris/bin:$PATH export DOCKER_HOST=unix:///home/chris/rootless/docker.sock # # To control docker service run: # systemctl --user (start|stop|restart) docker #
Take a look at the post-install advice in Listing 2.1. The binaries have been installed within your user's home directory under the bin/
directory. You can confirm that they are there with an ls
command.
The next thing to do is create three environment variables, as follows:
$ export XDG_RUNTIME_DIR=/home/$USER/rootless $ export PATH=/home/$USER/bin:$PATH $ export DOCKER_HOST=unix:///home/$USER/rootless/docker.sock
In the previous examples, for ease, $USER
is used in place of chris
.
You can also specify a different directory name here if you prefer. Before running the next command, we will need a directory to store our running container content and configuration, so create one now:
$ mkdir rootless
Now we can run this command to get rootless mode going, noting that we are using the preferred overlay2
storage driver:
$ bin/dockerd-rootless.sh --experimental --storage-driver overlay2
Listing 2.2 shows the end of the output, describing how /home/chris/rootless/docker.sock
has connected to Docker Engine in rootless mode.
Listing 2.2: Docker in Rootless Mode Has Run Successfully
WARN[2020-08-24T15:51:34.554236269+01:00] Not using native diff for overlay2, this may cause degraded performance for building images: failed to set opaque flag on middle layer: operation not permitted storage-driver=overlay2 INFO[2020-08-24T15:51:34.555462723+01:00] Docker daemon commit=48a66213fe graphdriver(s)=overlay2 version=19.03.12 INFO[2020-08-24T15:51:34.556309674+01:00] Daemon has completed initialization INFO[2020-08-24T15:51:34.602091497+01:00] API listen on /home/chris/rootless/docker.sock
If you run the following command, you will see the processes running for Docker, as the less privileged user:
$ ps -ef | grep docker
Listing 2.3 shows the results.
Listing 2.3: Rootless Mode Docker