Docker Security: Dissecting Namespaces, cgroups, and the Art of Misconfiguration

6 min read

May 25, 2025

Docker Security: Dissecting Namespaces, cgroups, and the Art of Misconfiguration

Table of contents

TL;DR

  • Understand how Docker containers isolate processes with namespaces, cgroups, and OverlayFS.
  • See why isolation ≠ security, and where common misconfigurations open real attack paths.
  • Meet Valeris, a Rust CLI that audits running containers for dangerous defaults.
  • Walk away with a checklist to keep your next deploy out of the breach headlines.

Welcome to the Series

If you’ve followed my work, you know I love application security testing. Lately, more clients rely on Docker and Kubernetes, yet I hadn’t explored the internals deeply until now.

To make this journey practical (and fun) I’m building Valeris, a Rust‑based CLI that scans running containers for misconfigurations. It’s part learning project, part real‑world utility and you get to watch (or help!) while I build.

In this first chapter:

  • You’ll learn what Docker is and how It works.
  • I’ll introduce Valeris and show you how it works.
  • And we’ll look at some common misconfigurations it can already detect.

Let’s go.

What Is Docker?

Docker is a platform that lets you package an app, its dependencies, and its environment into a container: a lightweight “virtual box” that shares the host’s kernel but runs in its own isolated space.

But what does that really mean?

When you run a Docker container, you’re not launching a full operating system like you would with a virtual machine. Instead, you're starting a regular process on the host... but with some clever isolation tricks applied. These tricks are built into the Linux kernel and revolve around three key mechanisms:

  1. Namespaces – what a process can see
  2. Control groups (cgroups) – what a process can use
  3. Overlay (Union) File Systems – what a process can write

Let’s break them down.

Namespaces – The illusion of being alone

Namespaces are like tinted glasses for processes. They limit what a process can see or interact with in the system.

Think of them as "personal illusions" applied to a process:
it thinks it's alone, but really it’s just been put in a carefully crafted sandbox.

Each namespace type controls a different part of that illusion:

Namespace What it isolates Analogy
pid Process IDs (PIDs) The process thinks it’s PID 1 (like init)
net Network interfaces, IPs, routes Gets its own “private” network
mnt Mount points / filesystems Sees only its own mounted directories
uts Hostname and domain name Can call itself vuln-container.local
ipc Shared memory (semaphores, etc.) Can’t talk to other processes via shared mem
user UID/GID mappings Can map its own root user differently
cgroup cgroup membership Hides host resource limits

Without namespaces:

  • A process sees all other running processes.
  • It shares the same network as the host.
  • It can access the same filesystem mounts.

With namespaces:

  • A process only sees its own little world.
  • It thinks it's PID 1 (like a fresh OS).
  • Its network is isolated, its mounts are separated, and its hostname can be totally fake.

And how does Docker apply this?

Docker uses a Linux syscalls called clone(2)and unshare(2) under the hood to create new namespaces when launching a container.

So when you type:

docker run debian:stable-slim

Docker is actually doing something like:

"Hey kernel, create a new process, but isolate it using these namespaces: PID, NET, MNT, UTS, USER… and maybe don’t tell it it’s just a guest."

That’s how each container ends up with its own environment, while still running on the same kernel as everything else.

Control Groups (cgroups) – Resource management for grown-ups

While namespaces handle what a process can see, control groups (cgroups) control what a process can use.

Think of cgroups as the resource police:
“You get two CPU cores, 512MB of RAM, and that’s it. No exceptions.”

In simple terms, cgroups limit, measure, and isolate resource usage of processes or groups of processes.

Here’s what you can control:

Resource Example usage
CPU Limit a container to 1 core, or 50% CPU time
Memory Cap RAM usage (and trigger OOM when exceeded)
I/O Limit disk read/write speeds
PIDs Limit how many processes it can spawn
Network Limit bandwidth (with more advanced setups)

Each cgroup is like a sandbox with a budget: it doesn’t care what the app is doing, but it ensures the app can’t exceed what it's allowed.

OverlayFS - Layer cake for containers

While namespaces isolate what a process sees, and cgroups limit what a process uses,
the union file system makes sure containers don’t accidentally trash your disk (or each other’s).

That’s right Docker containers don’t get a blank hard drive every time they start. Instead, Docker uses OverlayFS (a type of Union FS) to simulate a complete filesystem by stacking multiple layers.

Building a Docker container is like assembling a cake:

  1. 🎂 At the bottom: a read-only base image (e.g. debian:stable).
  2. 🧁 Next layer: your installed packages (nginx, python, etc.).
  3. 🍒 Then: your app files and configurations.
  4. ✍️ At the top: a writable layer that's unique to this running container.

When your container runs:

  • It reads files by scanning top-down through the layers.
  • It writes by copying files into the top writable layer only.

This technique is called copy-on-write, and it means:

  • Base layers remain untouched,
  • Changes are container-specific,
  • And teardown is fast, just discard the top layer.

This is useful because thanks to this Docker can:

  • Reuse the same base images efficiently.
  • Build fast, thanks to cached and layered image construction.
  • Stay isolated even if 10 containers use debian, they don’t overwrite each other.
  • Can be destroyed and rebuilt instantly, because only the writable layer is ephemeral.

Without this, each container would be a complete copy, slow, heavy, and repetitive.

Automating the Hunt for Misconfigurations

Now that we’ve covered the basics of how Docker works, let’s talk about the real reason we're here: misconfigurations.

As you might imagine, there are plenty of ways to configure a container poorly, making it vulnerable to privilege escalation, data leaks, or even host compromise. Some classic examples include:

  • Running the container as root (no user restrictions at all),
  • Using the --privileged flag (which disables most security protections),
  • Mounting sensitive directories like /proc or /var/run/docker.sock,
  • Leaking secrets through environment variables like API_KEY, DB_PASSWORD, or AWS credentials.

So yeah Docker’s isolation isn’t magic. And misconfigurations are surprisingly common, especially in fast-paced environments where security isn't always a priority.

That’s why I wanted to create a tool that could automate the process of identifying these weak configurations. Not just to save time, but to help me learn the ins and outs of container security along the way.

Yes, I know there are excellent tools out there already like Trivy, Dockle, and docker-bench-security and they’re incredibly powerful. But I strongly believe that building something from scratch gives you a deeper understanding of how things really work. And honestly? It’s more fun that way.

What is Valeris?

Valeris is a CLI tool I’m building in Rust to audit Docker (and soon Kubernetes) containers. It scans running containers for misconfigurations that could lead to real security issues. Things like root containers, excessive privileges, dangerous mounts, and exposed secrets.

The best part? I’m building it from scratch as I learn, and documenting the process in this blog series. It’s both a learning journey and (hopefully) a tool that can be genuinely useful.

Valeris is designed with a plugin-based architecture, which means:

  • It’s easy to extend as I learn more.
  • Each plugin can focus on a specific risk (e.g., user privileges, mounts, networking).
  • It makes it easier to explain concepts clearly in the blog, one layer at a time.

What Valeris Can Already Do

Right now, Valeris can help with a few key checks:

  • Detect if a container is running as the root user.
  • Check if it’s mounting sensitive folders like /proc or /sys.
  • Report network exposure, such as open ports or host networking.
  • Find environment variables that contain common secret patterns.

It’s still early-stage, but even these basic checks already help streamline container audits.

Why build this in Rust?

Glad you asked. I chose Rust because:

  • I wanted to learn it in a real-world context.
  • It gives me a tool that’s fast, memory-safe, and future-proof.
  • It’s widely used in Web3 and infrastructure tooling, which aligns with my interests.
  • And honestly? Rust makes you write better code even if it makes you suffer a little at first.

Also: building a tool while learning is painful… but extremely rewarding.

Wrapping Up

So, Docker is powerful but also dangerously easy to misconfigure. In this first chapter, we’ve seen what containers really are, why isolation isn't bulletproof, and how tools like Valeris can help flag the things that most people forget (or ignore) when deploying.

But this is just the beginning.

What’s Next?

In the next chapter:

  • We'll create a vulnerable on purpose container setup.
  • We’ll scan it with Valeris and walk through the results.
  • And we’ll dig into how the plugin system works under the hood how each security check is actually performed.

Useful links

Resources

Docker. “Docker Engine Security Documentation.” Available at: https://docs.docker.com/engine/security/

man7.org. “namespaces(7) – Linux Manual Page.” Available at: https://man7.org/linux/man-pages/man7/namespaces.7.html

The Linux Kernel Documentation. “Control Group v2.” Available at: https://docs.kernel.org/admin-guide/cgroup-v2.html

The Linux Kernel Documentation. “Overlay Filesystem.” Available at: https://docs.kernel.org/filesystems/overlayfs.html

Aqua Security. “Trivy” Available at: https://trivy.dev/latest/

Good with Tech. “Dockle: Container Image Linter for Security.” Available at: https://github.com/goodwithtech/dockle

Docker. “Docker Bench for Security.” Available at: https://github.com/docker/docker-bench-security

Enjoyed the article?

Subscribe to the newsletter and get technical insights, cybersecurity tips, and development content straight to your inbox. Or support my work with a coffee ☕ if you found it useful!

📫 Subscribe now ☕ Buy me a coffee