How To Migrate To Rootless Docker In Debian And Ubuntu Linux – OSTechNix

Read on ostechnix.com


Docker is a fantastic tool that lets you run applications in neat, isolated boxes called containers. This makes developing and shipping software much faster and more consistent. But there’s a small catch you should know about. By default, Docker often runs with ‘root’ privileges, the highest level of access on a Linux system. This can be a security risk. Thankfully, there’s a much safer way: Rootless Docker.

This guide will walk you through everything you need to know about rootless Docker migration. We will explain why you should switch and show you exactly how to migrate Rootful Docker setup to Rootless Docker step-by-step. Let’s make your containers more secure!

What is Rootless Docker?

Rootless mode in Docker is exactly what it sounds like: it allows you to run the Docker daemon and your containers as a regular, non-root user. This is a huge win for security.

Here’s why rootless Docker is useful:

It Prevents Security Problems : Running as a non-root user helps protect you from potential vulnerabilities in Docker or the container runtime. If a security issue happens inside a container, it can’t easily escape and affect your entire host system because it doesn’t have root access.

: Running as a non-root user helps protect you from potential vulnerabilities in Docker or the container runtime. If a security issue happens inside a container, it can’t easily escape and affect your entire host system because it doesn’t have root access. You Don’t Need ‘sudo’: You can install and manage Docker without needing root privileges. This is perfect for environments where you don’t have or want to use admin access.

The magic behind rootless mode is a Linux feature called user namespaces. Think of it as giving your user a special bubble to play in. Inside this bubble, your user can act like an admin, but they can’t affect anything outside of it.

This is different from other methods where the Docker daemon itself still runs as root. With rootless mode, both the daemon and the container run safely without root privileges.

Rootless Docker vs. Docker with Non-root User

Please note that running Docker as non-root user and running docker in rootless mode are different.

Rootless Docker (True Rootless)

Docker daemon itself runs as a non-root user

No docker group needed

group needed Uses user namespaces to map container root to unprivileged host user

Storage in user’s home directory ( ~/.local/share/docker/ )

) More secure but with limitations (no privileged operations, some networking restrictions)

Docker with Non-root User (Traditional)

Docker daemon still runs as root ( dockerd process)

process) Regular users are added to the docker group

group Users can run docker commands without sudo

commands without Containers still have root privileges on the host system

Uses standard locations like /var/lib/docker/

Security concern: Being in docker group is equivalent to having root access

Hope you understand the difference between these two.

Getting Ready for the Rootless Docker Setup

Before we start, you need just a few things. The process is smooth if you have these prerequisites ready.

A Linux System : Ubuntu is highly recommended by Docker team, because its kernel has great support for the overlay2 storage driver, which rootless mode needs. However, Docker works fine in any Linux distribution. I tested this setup on Debian 13 and Ubuntu 24.04 LTS, it works out of the box.

: by Docker team, because its kernel has great support for the storage driver, which rootless mode needs. However, Docker works fine in any Linux distribution. I tested this setup on Debian 13 and Ubuntu 24.04 LTS, it works out of the box. A Few Key Packages : You’ll need to install uidmap (which contains tools called newuidmap and newgidmap ) and dbus-user-session .

: You’ll need to install (which contains tools called and ) and . User ID Ranges : Your system needs to give your user a block of user IDs (UIDs) and group IDs (GIDs) to use for its containers. You’ll need to set this up in the /etc/subuid and /etc/subgid files. A block of 65,536 is usually enough for most needs.

: Your system needs to give your user a block of user IDs (UIDs) and group IDs (GIDs) to use for its containers. You’ll need to set this up in the and files. A block of 65,536 is usually enough for most needs. Backup Important Data: Make sure you have backed up all important data that you can’t afford to lose.

Step-by-Step Guide To Migrate Rootful Docker to Rootless Docker

I assume you already have Docker installed and running in rootful mode on your Linux system. If not, follow the given links to setup Docker on your preferred system.

Step 1: Stop and Disable Your Old Rootful Docker Setup

First things first, if you have the standard, system-wide Docker running (i.e. Rootful Docker), you need to stop and disable it. This prevents any conflicts.

Run these commands in your terminal:

sudo systemctl disable –now docker.service docker.socket

sudo rm /var/run/docker.sock

This stops Docker and removes its old socket file.

Step 2: Install the Necessary Tools

Next, let’s install the packages we mentioned earlier.

sudo apt install -y uidmap dbus-user-session systemd-container docker-ce-rootless-extras

This single command gets you uidmap for user mapping, dbus-user-session for managing your session, and docker-ce-rootless-extras , which includes a helpful setup tool.

Step 3: Log In the Right Way (This is Important!)

Now, you need to log in as the user who will run rootless Docker. You can create a new user or use your existing one.

More importantly, you must log in using a method that supports pam_systemd . Do not use sudo su . Using the right method automatically sets up an important environment variable called $XDG_RUNTIME_DIR . The easiest way is with the machinectl command, which you installed in the previous step.

sudo machinectl shell $(whoami)@

This logs you into a new shell as your current user, the correct way.

If you want to log in as different user (E.g. senthil), just mention it as shown below:

sudo machinectl shell senthil@

If you see the following output after running the above command, you’re good to go:

Connected to the local host. Press ^] three times within 1s to exit session.

Step 4: Install Rootless Docker

You are now logged in as your user and ready to install. Run the rootless docker setup script:

dockerd-rootless-setuptool.sh install

The script will set up a systemd service for Docker that runs under your user account.

After successful rootless Docker migration, you will an output like below:

[…]

debian13desktop dockerd-rootless.sh[5760]: time=”2025-09-05T18:28:28.173512284+05:30″ 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: 28.4.0

API version: 1.51

Go version: go1.24.7

Git commit: d8eb465

Built: Wed Sep 3 20:57:38 2025

OS/Arch: linux/amd64

Context: default

Server: Docker Engine – Community

Engine:

Version: 28.4.0

API version: 1.51 (minimum version 1.24)

Go version: go1.24.7

Git commit: 249d679

Built: Wed Sep 3 20:57:38 2025

OS/Arch: linux/amd64

Experimental: false

containerd:

Version: 1.7.27

GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da

runc:

Version: 1.2.5

GitCommit: v1.2.5-0-g59923ef

docker-init:

Version: 0.19.0

GitCommit: de40ad0

rootlesskit:

Version: 2.3.4

ApiVersion: 1.1.1

NetworkDriver: slirp4netns

PortDriver: builtin

StateDir: /run/user/1001/dockerd-rootless

slirp4netns:

Version: 1.2.1

GitCommit: 09e31e92fa3d2a1d3ca261adaeb012c8d75a8194

+ systemctl –user enable docker.service

Created symlink ‘/home/ostechnix/.config/systemd/user/default.target.wants/docker.service’ \u2192 ‘/home/ostechnix/.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 ostechnix`

[INFO] Creating CLI context “rootless”

Successfully created context “rootless”

[INFO] Using CLI context “rootless”

Current context is now “rootless”

[INFO] Make sure the following environment variable(s) are set (or add them to ~/.bashrc):

export PATH=/usr/bin:$PATH

[INFO] Some applications may require the following environment variable too:

export DOCKER_HOST=unix:///run/user/1001/docker.sock

Step 5: Update Your Environment

After the installation finishes, the script will show you a few lines to add to your shell’s startup file, like ~/.bashrc .

These lines set the PATH and DOCKER_HOST environment variables so your terminal can find and talk to the new rootless Docker daemon.

In my case, I have added the following environment variables:

echo ‘export PATH=/usr/bin:$PATH’ >> ~/.bashrc echo ‘export DOCKER_HOST=unix:///run/user/1001/docker.sock’ >> ~/.bashrc

After adding them to your ~/.bashrc file and then run the following command to apply the changes immediately:

source ~/.bashrc

Step 6: Start and Manage Your New Rootless Docker

Congratulations, you’re all set up! Managing your rootless Docker is slightly different.

To start and enable rootless Docker daemon, run:

systemctl –user enable docker systemctl –user start docker

Notice the –user flag.

These commands enable and start the Docker service for your user.

To make Docker start automatically when you boot your machine, you need to enable “lingering” for your user. This allows your user to run long-running services even when you’re not logged in.

Enable lingering so Docker runs after logout:

sudo loginctl enable-linger $(whoami)

This command turns on lingering.

Step 7: Verify Rootless Docker Installation

To confirm Docker is running in rootless mode:

docker info | grep -i rootless

If you see:

rootless […]

…then Docker is running rootless successfully.

You can also test it by running all Docker commands without sudo or root :

docker run hello-world

Rootless Docker Limitations

Rootless mode is fantastic, but it comes with a few known limitations.

Networking is different : The IP address of a container is not reachable from the host. You should always use port mapping (e.g., docker run -p 8080:80 ) to access services running in a container. Also, features like –net=host are namespaced, meaning they won’t use the host’s actual network directly.

: The IP address of a container is not reachable from the host. You should always use port mapping (e.g., ) to access services running in a container. Also, features like are namespaced, meaning they won’t use the host’s actual network directly. Privileged Ports : You can’t map to ports below 1024 (like port 80) by default. You can either use a higher port (like 8080) or change system settings to allow it.

: You can’t map to ports below 1024 (like port 80) by default. You can either use a higher port (like 8080) or change system settings to allow it. Resource Limits: Limiting container resources like CPU or memory requires your system to use cgroup v2. If not, these flags will be ignored.

Troubleshooting

Here are some common troubleshooting steps you might encounter when migrating to or using rootless Docker.

Installation and Startup Problems

Several issues can arise during the initial setup and when starting the rootless Docker daemon.

systemd not detected or Failed to connect to bus :

These errors often occur if you switch to a non-root user with a command like sudo su or sudo -iu testuser .

The correct way to log in is using a method that supports pam_systemd , which properly sets up the necessary environment.

The recommended command is:

sudo machinectl shell @

Daemon does not start automatically:

To have the rootless Docker service start on boot, you must enable “lingering” for your user account. This allows your user to run long-running services even when you are not logged in.

You can do this with the command:

sudo logctl enable-linger $(whoami)

Errors related to User Namespaces:

operation not permitted : If you see this error, it’s likely because your system is not configured to allow unprivileged users to create user namespaces. You can fix this by setting kernel.unprivileged_userns_clone=1 in your /etc/sysctl.conf file and then running sudo sysctl –system .

: If you see this error, it’s likely because your system is not configured to allow unprivileged users to create user namespaces. You can fix this by setting in your file and then running . no space left on device : This message can appear if the maximum number of user namespaces is too low. To fix it, you can set user.max_user_namespaces=28633 in /etc/sysctl.conf and apply the change with sudo sysctl –system .

: This message can appear if the maximum number of user namespaces is too low. To fix it, you can set in and apply the change with . No subuid ranges found for user : This error means you have not configured subordinate UIDs and GIDs for your user in the /etc/subuid and /etc/subgid files. Rootless mode requires at least 65,536 UIDs/GIDs to be allocated for the user.

: This error means you have not configured subordinate UIDs and GIDs for your user in the and files. Rootless mode requires at least 65,536 UIDs/GIDs to be allocated for the user. could not get XDG_RUNTIME_DIR : The $XDG_RUNTIME_DIR environment variable is essential and is normally set automatically when you log in correctly via pam_systemd . If it’s not set, it can cause problems.

Image Pulling ( docker pull ) Errors

When pulling images, you might encounter issues related to file ownership and permissions within the container layers.

lchown : invalid argument : This typically means the number of subordinate UIDs/GIDs available in your /etc/subuid and /etc/subgid files is insufficient for the image you’re trying to pull. While requirements vary, having 65,536 IDs is enough for most images.

: This typically means the number of subordinate UIDs/GIDs available in your and files is insufficient for the image you’re trying to pull. While requirements vary, having 65,536 IDs is enough for most images. lchown : operation not permitted : This error often happens if your Docker data directory ( ~/.local/share/docker ) is located on an NFS mount. You can work around this by changing the data-root in your Docker configuration to a directory that is not on an NFS filesystem.

Container Running ( docker run ) Errors

Once the daemon is running, you may face issues when you try to run a container.

OCI runtime create failed / connection reset by peer : On a system using cgroup v2, this error can occur if the D-Bus daemon is not active for your user session. To fix this, you may need to install the dbus-user-session package and then log out and back in again.

: On a system using cgroup v2, this error can occur if the D-Bus daemon is not active for your user session. To fix this, you may need to install the package and then log out and back in again. Resource limits are ignored : Flags like –cpus , –memory , and –pids-limit only work if your system is running with cgroup v2 and systemd. If docker info shows the Cgroup Driver as none , these flags will be ignored.

: Flags like , , and only work if your system is running with cgroup v2 and systemd. If shows the as , these flags will be ignored. Bugs after migration: One user noted that they encountered bugs in their containers after migrating. The solution was to stop and remove all containers that were previously started under the old, rootful Docker installation.

Networking Issues

Networking in rootless mode is handled differently, which can lead to some common points of confusion.

Cannot expose privileged ports : You cannot map a container port to a host port below 1024 by default. For example, docker run -p 80:80 will fail. The easiest solution is to use a higher port, like 8080 . Alternatively, you can change system settings to allow it.

: You cannot map a container port to a host port below 1024 by default. For example, will fail. The easiest solution is to use a higher port, like . Alternatively, you can change system settings to allow it. ping command does not work : On some systems, ping from within a container might fail. This can usually be fixed by adding net.ipv4.ping_group_range = 0 2147483647 to your /etc/sysctl.conf file.

: On some systems, from within a container might fail. This can usually be fixed by adding to your file. Container IP address is unreachable from the host : This is expected behaviour. The IP address shown in docker inspect exists inside a separate network namespace and cannot be reached directly from the host. You should always use port mapping, like docker run -p : , to access services inside the container. The same applies to –net=host , which is also namespaced.

: This is expected behaviour. The IP address shown in exists inside a separate network namespace and cannot be reached directly from the host. You should always use port mapping, like , to access services inside the container. The same applies to , which is also namespaced. Slow network performance: By default, rootless Docker uses network drivers that can be slow. Installing slirp4netns (version 0.4.0 or later) can improve network throughput.

Uninstall Rootless Docker and Switch Back to Rootful Docker

If you’re no longer need rootless Docker or want to switch back to rootful Docker, simply remove rootless Docker using command:

dockerd-rootless-setuptool.sh uninstall

This command will stop the user-enabled docker service, and switch to default context.

+ systemctl –user stop docker.service

+ systemctl –user disable docker.service

Removed ‘/home/ostechnix/.config/systemd/user/default.target.wants/docker.service’.

[INFO] Uninstalled docker.service

[INFO] Deleted CLI context “rootless”

Current context is now “default”

[INFO] Configured CLI to use the “default” context.On Debian and Ubuntu:

[INFO]

[INFO] Make sure to unset or update the environment PATH, DOCKER_HOST, and DOCKER_CONTEXT environment variables if you have added them to `~/.bashrc`.

[INFO] This uninstallation tool does NOT remove Docker binaries and data.

[INFO] To remove data, run: `/usr/bin/rootlesskit rm -rf /home/ostechnix/.local/share/docker`

Unset the environment PATH, DOCKER_HOST, and DOCKER_CONTEXT environment variables if you have added them to ~/.bashrc . To do so, simply remove the lines that you have added in the earlier step 5.

Remove the data using command:

/usr/bin/rootlesskit rm -rf /home/ostechnix/.local/share/docker

Please note that we have only removed the rootless Docker setup. The docker binaries still exist in our system.

Finally enable the docker service on system startup using commands:

sudo systemctl enable docker

sudo systemctl start docker

Check the service status:

sudo systemctl status docker

We’re now back to Rootful Docker mode.

Frequently Asked Questions (FAQ)

Q: Is rootless Docker slower than rootful Docker? A: Yes, rootless Docker can be slightly slower because it uses user-mode networking, but the security trade-off is often worth it. Q: Can I run Docker Compose with rootless Docker? A: Yes. Docker Compose V2 works seamlessly: docker compose up -d Q: I cannot connect to the Docker daemon. What should I do? A: Make sure your environment variable is set: export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock

Add it to your ~/.bashrc permanently. Q: My network is very slow and I can’t access the Internet A: Rootless Docker uses slirp4netns for networking. If containers can’t access the internet or has slow network issues: sudo apt install -y slirp4netns Q: Does rootless Docker support all container images? A: Yes, but some containers that require privileged access or specific kernel modules may not work.

Conclusion

Migrating to rootless Docker is one of the best moves you can make for a more secure container environment. By running Docker as a non-root user, you significantly reduce your system’s attack surface and protect it from potential container breakouts.

While there are a few limitations to consider, the huge security benefits make it a worthwhile change for nearly everyone.

Now you can enjoy the power of Docker with greater peace of mind.

Happy (and safe) containerising!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top