Linux Namespaces

Namespaces are the kernel feature that makes containers possible. They give a process a private view of a system resource — its own process tree, its own network interfaces, its own hostname, its own filesystem mounts. The host is unaffected; the process just sees less than the full picture.

The 7 Namespace Types

NamespaceIsolatesFlagWhat container gets
PIDProcess IDsCLONE_NEWPIDOwn process tree, PID 1 = container init
NETNetwork stackCLONE_NEWNETOwn interfaces, routes, iptables, sockets
MNTMount pointsCLONE_NEWNSOwn filesystem view, can't see host mounts
UTSHostname/domainCLONE_NEWUTSOwn hostname (docker container has its own)
IPCSystem V IPC, POSIX MQCLONE_NEWIPCOwn shared memory, message queues, semaphores
USERUser/Group IDsCLONE_NEWUSERUID 0 in container maps to non-root on host
CGROUPcgroup rootCLONE_NEWCGROUPOwn view of cgroup hierarchy

PID Namespace — Isolated Process Tree

How can a container have PID 1 when the host has its own PID 1? The PID namespace creates a new numbering space. The first process in the new namespace gets PID 1 from its own perspective. From the host, that process has a normal PID (say, 12345). The container process can't see or signal processes outside its namespace. If PID 1 in the container dies, all container processes die — just like on a real system.
# Create a new PID namespace with unshare unshare --pid --fork --mount-proc bash # Now inside the new namespace: ps aux # PID USER COMMAND # 1 root bash ← this bash is PID 1! # 2 root ps aux # From host (different terminal): ps aux | grep bash # 12345 root bash ← host sees the real PID # List namespaces: ls -la /proc/self/ns/ # pid -> pid:[4026532456] ← unique namespace ID (inode number) # net -> net:[4026531992] # mnt -> mnt:[4026531840] # uts -> uts:[4026531838]

User Namespace — Rootless Containers

How can a container run as root without being root on the host? User namespaces map UIDs inside the namespace to different UIDs outside. UID 0 inside the container can map to UID 1000 on the host. The process thinks it's root and can do root things inside the namespace, but from the host's perspective it's just an unprivileged user. This is the foundation of rootless containers (podman, Docker rootless mode).
# Create user namespace where we appear as root unshare --user --map-root-user bash # id # uid=0(root) gid=0(root) groups=0(root) ← looks like root # cat /proc/self/uid_map # 0 1000 1 ← uid 0 inside = uid 1000 outside # Docker rootless: user namespace maps container root to your user # podman run --rm alpine id # uid=0(root) gid=0(root) ← root inside container # (but on host: uid=1000 — your normal user) # Why this matters for security: # A container escape (root in container) doesn't automatically mean # root on the host — still mapped to an unprivileged user

Creating Namespaces — The Syscalls

# Three ways to create namespaces: # 1. clone() — create child process in new namespace # (this is what Docker uses) # clone(child_func, stack, CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWNS, ...) # 2. unshare() — current process enters new namespace # (the 'unshare' command wraps this syscall) unshare --pid --net --mount --uts --ipc bash # 3. setns() — join an existing namespace # (this is how 'docker exec' works — joins container's namespaces) nsenter --target 12345 --pid --net bash # Now in the same namespaces as process 12345 # Inspect a container's namespaces: docker inspect mycontainer --format '{{.State.Pid}}' # 12345 ls -la /proc/12345/ns/

Persistent Namespaces — Without a Process

# Namespaces normally die when last process leaves # But you can bind-mount them to keep them alive # Named network namespaces (ip netns) persist in /var/run/netns/ ip netns add mynet ls /var/run/netns/mynet ← bind-mount keeps it alive # Kubernetes: network namespace lives in /var/run/netns/ # Pause container holds the namespace; app containers join it via setns() # This is why all containers in a pod share network — same netns

Frequently Asked Questions

What will I learn here?

This page covers the core concepts and techniques you need to understand the topic and progress confidently to the next lesson.

How should I use this page?

Start with the overview, then follow the section links to deepen your understanding. Use the table of contents on the right to jump to specific sections.

What should I read next?

Use the navigation below to continue to the next lesson or explore related topics.