Ayush Pande is a PC hardware and gaming writer. When he's not working on a new article, you can find him with his head stuck inside a PC or tinkering with a server operating system. Besides computing, his interests include spending hours in long RPGs, yelling at his friends in co-op games, and practicing guitar.
Although LXCs and Podman have their own perks, Docker remains the most popular container runtime for home labbers, and for good reason. Typical FOSS tools tend to ship with Docker images that work right out-of-the-box, with Compose configs simplifying the deployment process even further. Combine that with the ultra-simple Docker management commands, and it’s pretty easy to tinker with this runtime, even when you’re a complete beginner to containerized services.
That said, Docker has its own set of quirks. Its Swarm functionality isn’t as powerful as Kubernetes, while its daemon service can hog more resources compared to the daemonless architecture of certain rivals. However, my biggest issue with Docker is that it runs with root-level access by default, which is one heck of a security nightmare if you’re as fond of experimenting with random GitHub repos as I am.
A fresh Docker installation runs the daemon process (and containers) with root privileges
This increases the blast radius of vulnerable containers
If you’ve ever worked with Linux distributions, you’re probably aware that your setup has an admin account with unrestricted system access called root. When you install Docker for the first time, the underlying daemon process, dockerd, binds itself to the Unix socket owned by this root user. Unless you tweak certain parameters in a container’s Dockerfile, the environments spawned from dockerd also run with root privileges, and that’s where things get hairy from a security standpoint.
Unlike virtual machines, which emulate a fresh kernel and OS, containers share the kernel with the underlying host machine. Combine that with the fact that the dockerd daemon has full-on root-level access to the system, and Docker’s rootful design becomes a massive security nightmare. Let’s say a container image has some malicious code tacked on in a recent update. On a default Docker setup, it’d be a lot easier for this malicious code to escape its containerized confines and wreak havoc on your host machine.
Heck, it’s not just malware-riddled container images that you need to watch out for, either. If you accidentally mount a system directory to a container, your FOSS service will gain full-on superuser access to the critical files in this folder. And one botched container experiment is all it’d take to render the underlying host inaccessible.
I stick to rootless Docker setups on my self-hosting workstations
It’s also fairly easy to enable
Technically, there are a couple of ways to make your Docker experiments more secure. You could modify the Dockerfile to force the container to run with non-root privileges. Or, for folks who use pre-built Docker images, you could override the user manually in the docker run or compose.yml files. But since both methods require you to repeat the same steps for every Docker container, this process can get tedious before long.
Instead, I recommend going down the rootless mode route, which also tackles the problem of the dockerd daemon running with superuser privileges. Since the container and the daemon remain locked behind an unprivileged user, a malfunctioning Docker environment can’t get full-on root access to the host machine with this mode. Better yet, you can just enable it once by running the following commands and have every new Docker container run with rootless permissions:
sudo apt install uidmap -y
curl -fsSL https://get.docker.com/rootless | sh
export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix:///run/user/1000/docker.sock
That said, rootless mode has its own set of caveats
Personally, I stick with rootless containers on my Docker workstations, and most of the services in my FOSS arsenal work well without any issues. However, running Docker environments with non-root privileges can introduce some minor issues. For one, you can’t map privileged ports for containers on a rootless Docker setup, meaning any ports under 1024 are off-limits for your containerized environments. It’s not a big deal for typical productivity apps, archival utilities, or backup services, but network tools are a different story altogether.
Take Pi-hole, for example, which needs access to port 53 for core DNS services. Of course, you can still deploy it on a rootless setup by tweaking certain config files, but it’s not as easy as executing a docker run command on a default Docker configuration. Besides the networking aspect, you’ll also need to deal with certain storage constraints, especially if your experiments involve OverlayFS mounts. Likewise, limiting resources for containers via cgroups v2 can be a bit of a hassle, and the same holds true for custom AppArmor profiles.
But for folks looking to tinker with productivity tools, quirky container images, and data archival utilities, it’s a good idea to enable rootless mode on Docker.





