Running rootless Docker allows non-root users to run the Docker daemon and containers without special privileges. This adds an extra layer of security in an event a container gains access to its host.
Rootless mode has become part of Docker Engine on
v20.10. There are some known limitations that you should be aware of, see here. And, if you want to learn more about how it works, check out this article.
I'm installing Rootless Docker on a vanilla
Debian 10 (Buster) x86_64; but this mode is supported in other distributions as well, more details here.
lsb_release -d && arch (out)Description: Debian GNU/Linux 10 (buster) (out)x86_64
Installing Rootless Docker
root (or using
sudo, if you have that configured), let's create a new user called
docker with its home folder at
adduser --home /srv/docker docker (out)Adding user `docker` ... (out)Adding new group `docker` (1001) ... (out)Adding new user `docker` (1001) with group `docker` ... (out)Creating home directory `/srv/docker` ... (out)Copying files from `/etc/skel` ... (out)New password: (out)Retype new password: (out)passwd: password updated successfully (out)Changing the user information for docker (out)Enter the new value, or press ENTER for the default (out) Full Name : (out) Room Number : (out) Work Phone : (out) Home Phone : (out) Other : (out)Is the information correct? [Y/n] Y
2. We need to change these kernel settings before we start:
kernel.unprivileged_userns_clone = 1enables unprivileged users to create namespaces.
net.ipv4.ip_unprivileged_port_start = 0allows users to open privileged ports below 1024.
Load the new attributes using
sysctlafter the changes.
cat > /etc/sysctl.d/50-rootless.conf <<EOL (out)kernel.unprivileged_userns_clone = 1 (out)net.ipv4.ip_unprivileged_port_start = 0 (out)EOL sysctl --system
3. We should also load the
overlay2 module, the recommended storage driver:
Reload new system modules using the
echo "options overlay permit_mounts_in_userns=1" > \ (out)/etc/modprobe.d/50-rootless.conf systemctl restart systemd-modules-load.service
4. That's all needed from the
root for now. Let's open a new terminal or
ssh session with the newly created
5. Download and run the Rootless Docker install script:
curl -fsSL https://get.docker.com/rootless | sh (out)... (out)[INFO] Installed docker.service successfully. (out)[INFO] To control docker.service, run: `systemctl --user (start|stop|restart) docker.service` (out)[INFO] To run docker.service on system startup, run: `sudo loginctl enable-linger docker` (out) (out)[INFO] Make sure the following environment variables are set (or add them to ~/.bashrc): (out) (out)export PATH=/srv/docker/bin:$ (out)export DOCKER_HOST=unix:///run/user/1001/docker.sock
6. If the install was successful, we want to add the Docker environment variables to
.bashrc, so the Docker commands are easily available in future logins:
cat >> ~/.bashrc <<EOL (out) (out)# Docker Environment (out)export PATH=/srv/docker/bin:$PATH (out)export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock (out)EOL
7. Finally, to enable the service to start automatically during the system boot:
systemctl --user enable docker su -c "loginctl enable-linger $(whoami)"
8. I'd recommend a
reboot at this point, just to make sure everything is working. You should be able to run a
systemctl status to confirm the Docker daemon is running:
systemctl --user status docker (out)● docker.service - Docker Application Container Engine (Rootless) (out) Loaded: loaded (/srv/docker/.config/systemd/user/docker.service) (out) Active: active (running) since Sat 2021-03-20 00:01:53 EDT; 11h ago (out) Docs: https://docs.docker.com/engine/security/rootless/ (out) Main PID: 522 (rootlesskit) (out) CGroup: /user.slice/user-1001.slice/[email protected]/docker.service
Installing Docker Compose
Docker Compose makes it easier to document, configure and manage your Docker containers.
There are many different ways on how to install it but for our rootless Docker, I decided to go meta and run it inside a container as well; which is pretty simple to do.
1. Download the small install script:
At the time this article was written the latest Docker Compose released was
v1.28.5, but you should check current version here.
curl -L --fail https://github.com/docker/compose/releases/download/1.28.5/run.sh \ (out)-o $HOME/bin/docker-compose
2. Make it executable:
chmod +x $HOME/bin/docker-compose
3. When you run
docker-compose for the first time, it will download all required images:
docker-compose version (out)docker-compose version 1.28.5, build c4eb3a1 (out)docker-py version: 4.4.4 (out)CPython version: 3.7.10 (out)OpenSSL version: OpenSSL 1.1.1j 16 Feb 2021
While I don't fully intent to go over a NGINX installation, I didn't want to leave this article without something less tangible to test our rootless Docker setup.
In fact, this NGINX setup doesn't differ from your typical, root-enabled, Docker.
1. Let's create some folders structure to house our new NGINX container:
mkdir -p /srv/docker/containers/nginx && cd /srv/docker/containers/nginx
2. Using a
docker-compose.yml file, we will create a
nginx container using the
nginx:alpine image and open the port
vi docker-compose.yml (out)version: "3.9" (out)services: (out) nginx: (out) container_name: nginx (out) image: nginx:alpine (out) ports: (out) - "80:80"
3. Finally, start your new container, when ran for the first time it will download any required images:
4. On your browser, open
http://your.docker.ip/ and you should be welcomed by NGINX's default page: