Back to articles
Technology Insight

Docker Container Security: Configuring User Namespaces on VPS to Prevent Container Breakout Attacks

June 3, 2026

Introduction to the Container Isolation Illusion

In the modern cloud-native landscape, Docker has revolutionized how businesses deploy and scale applications. Virtual Private Servers (VPS) frequently host multiple containerized services, ranging from web servers to internal databases. However, a common and dangerous misconception among system administrators is that Docker containers are completely isolated virtual environments by default.

Standard containers share the host operating system's kernel. Most importantly, unless explicitly configured otherwise, the root user inside a container is the exact same root user (UID 0) on the host system. If an attacker manages to exploit an application vulnerability within the container and escapes, they instantly inherit root-level privileges over your entire VPS. This catastrophic scenario is known as a Container Breakout. To mitigate this risk, enterprise security architectures rely on a powerful Linux kernel feature: User Namespaces (userns).

Understanding Container Breakout Vulnerabilities

Before diving into the technical configuration, it is critical to understand how an attacker can leverage default Docker settings to compromise a host machine. When a container runs without user namespace isolation, the kernel enforces permissions based on standard User IDs (UIDs) and Group IDs (GIDs).

The Mechanics of a Breakout

If a process inside a container runs as UID 0 (root), and that process interacts with host resources via misconfigured volume mounts, exposed sockets (such as /var/run/docker.sock), or kernel vulnerabilities, the kernel treats those actions as if they were initiated by the host's root user. Common vectors for container breakouts include:

  • Directory Traversal via Volume Mounts: Mounting sensitive host directories (like /etc or /root) into a container allows a containerized root user to modify host system files.
  • Kernel Exploits: Weaknesses in the shared Linux kernel (e.g., Dirty COW) can be exploited from inside the container to execute code on the host.
  • Privileged Containers: Running a container with the --privileged flag disables almost all security mechanisms, making breakout trivial.
Security Note: Operating without User Namespaces means your host security is only as strong as the perimeter security of the application running inside your container.

What are User Namespaces?

User Namespaces are a feature of the Linux kernel that isolates security-related attributes, specifically UIDs and GIDs. When enabled in Docker, it maps the root user inside the container to a non-privileged, high-range UID on the host system (for example, mapping container UID 0 to host UID 165536).

As a result, inside the container, the application believes it has full administrative privileges, allowing it to manage internal packages, bind to privileged ports (like 80 or 443), and manipulate system files. However, if an attacker breaks out of the container to the VPS host, they are viewed by the host kernel merely as an unprivileged user with no authority to modify system configurations, access other users' data, or compromise the OS.

Step-by-Step Guide: Configuring User Namespaces on Docker

Implementing User Namespaces on your VPS requires altering the Docker daemon configuration and ensuring the host operating system has sub-UID and sub-GID ranges allocated. Follow these steps to secure your environment.

Step 1: Check Current User Mapping

First, verify how your containers currently view the root user. Run a standard container and check the process ownership from the host perspective:

docker run -d --name security_test alpine sleep 3600
ps aux | grep sleep

If the output shows that the sleep command is running as root, your system is currently exposed to potential breakout elevation.

Step 2: Configure Sub-UID and Sub-GID Ranges

Modern Linux distributions automatically create allocation ranges for users, but we must ensure a dedicated range exists for the Docker daemon. Check the files /etc/subuid and /etc/subgid. You should see entries similar to:

dockremap:165536:65536

This entry indicates that the user dockremap is allowed to map 65,536 subordinate UIDs starting from UID 165536. If these entries do not exist, you can create them manually or let Docker handle it dynamically by defining a generic remapping option.

Step 3: Modify the Docker Daemon Configuration

To enable user namespaces globally for all containers, you need to edit the Docker daemon configuration file, located at /etc/docker/daemon.json. If the file does not exist, create it.

Add the userns-remap property to the JSON object:

{
  "userns-remap": "default"
}

Setting the value to "default" instructs Docker to automatically create a dedicated host user and group named dockremap and handle the UID/GID mapping seamlessly.

Step 4: Restart the Docker Service

Apply the changes by restarting the Docker daemon on your VPS:

sudo systemctl restart docker

Upon restart, Docker will initialize a fresh storage directory specifically for remapped containers (typically located at /var/lib/docker/165536.165536/) to prevent unprivileged containers from accessing existing host-owned container images.

Step 5: Verify the Security Isolation

Launch a new container to verify that the configuration was successful:

docker run -d --name secure_test alpine sleep 3600

Now, check the process table on your host machine again:

ps aux | grep sleep

The output should no longer display root in the user column. Instead, it will display a high-number UID (e.g., 165536), proving that the containerized root user has been successfully jailed and downgraded on the host VPS.

Potential Trade-offs and Best Practices

While User Namespaces dramatically elevate your security posture, they introduce operational constraints that engineering teams must manage proactively.

  • Volume Permissions: Because container root is mapped to an unprivileged host UID, existing files mounted via -v or --volume may result in "Permission Denied" errors. You must change the ownership of host-mounted directories to match the subordinate UID range (e.g., chown -R 165536:165536 /path/to/host/dir).
  • Network Modes: Using the --net=host flag is incompatible with user namespaces, as it would expose the host's network stack to an isolated user namespace, creating a logical conflict.
  • Read-Only Root Filesystems: For maximum security, combine user namespaces with the --read-only flag when running containers to prevent any modification of the container's own binaries.

Conclusion

Securing a VPS against container breakout attacks is a vital requirement for modern business infrastructure. Relying solely on default Docker isolation leaves the system vulnerable to exploitation. By implementing User Namespaces, you add a robust layer of defense-in-depth, ensuring that even if an application layer is entirely compromised, your underlying host operating system remains protected and strictly off-limits to attackers.

Docker Container Security: Configuring User Namespaces on VPS to Prevent Container Breakout Attacks | DPTCloud