Chapter 6: Rootless containers
The introduction explains why rootless Podman is valuable on shared systems and sets up a closer look at how it works and where it can cause problems.
After this chapter you will be able to
- Rootless workload security boundary. Explain why sharing a root-running container daemon is risky and why running each user's Podman workloads under that user's account is safer, especially if a container escapes.
- Initial user namespace setup. State that setting up the user namespace is the first thing Podman needs to do when running the rootless container in this example. Explain that the section introduces this step but leaves why and how it works for the next section.
- Multiple image file owners. Explain why an image containing files owned by several UIDs poses a problem for a rootless user and why Podman needs a user namespace to handle it.
- Subordinate UID mapping. Describe how Podman maps the user’s host UID to UID 0 inside its user namespace and maps additional inside UIDs to subordinate host UIDs listed in /etc/subuid and /etc/subgid. Explain how podman unshare and /proc/self/uid_map reveal that mapping.
- Mapped ownership and access limits. Trace how a file’s owner appears inside versus outside the user namespace, and explain why being root inside it does not grant access to host files whose UIDs are unmapped.
- Namespaced capability boundaries. Explain that root’s powers are divided into Linux capabilities and that capabilities held inside a user namespace, such as CAP_CHOWN and CAP_SETUID, operate only on mapped UIDs and GIDs. Describe why Podman also needs CAP_SYS_ADMIN to mount container filesystems.
- Isolated rootless filesystem mounts. Describe how a mount namespace confines Podman’s container mounts to a separate view of the filesystem and why it must be used alongside a user namespace. Explain that the kernel still restricts which filesystem types rootless processes may mount.
- Rootless namespace startup. Trace how Podman’s first container run after login reads /etc/subuid and /etc/subgid, combines their entries with the user’s current UID and GID to create a user namespace, and launches the podman pause process to hold the user and mount namespaces open.
- Shared rootless namespace. Explain that later Podman commands join the pause process’s namespaces to avoid namespace startup and shutdown races, and that a rootless user’s containers share one user namespace by default so they can share content and other namespaces.
- Local image check and pull. Explain that Podman first checks local container storage for the image; if it is absent, Podman uses containers/image to contact the registry and pull the manifest, config, and layers.
- Ordered image layer storage. Describe how containers/storage reassembles the copied layers in order, creates each layer over the previous one in local container storage, and untars its contents.
- Rootless layer ownership mapping. Explain that, while unpacking layers, containers/storage changes file ownership to the tarball's UIDs and GIDs using CAP_CHOWN in the user namespace, and that creating content fails if a specified UID or GID is not mapped there.
- Container creation and writable layer. Trace how Podman creates a container after the image and storage are ready: it adds the container to its internal database, asks containers/storage to create and mount writable disk space as a layer above the image, and then proceeds to network configuration.
- Rootless networking constraints. Explain why rootless Podman uses slirp4netns instead of configuring container networking with CNI plugins. Distinguish permission to create a network namespace from permission to create network devices or change firewall rules.
- User mode packet routing. Trace how slirp4netns connects a container’s network namespace to host networking, including the 8080:8080 port mapping, the TAP device, user-space packet handling, and host socket operations.
- Conmon startup and cleanup. Trace how Podman starts conmon for a container, directs it to use the configured OCI runtime (usually crun or runc), and arranges for `podman container cleanup $CTRID` to run when the container exits.
- OCI runtime kernel configuration. Explain how the OCI runtime reads the OCI spec file and prepares the kernel and container environment, including namespaces, cgroups v2, security settings, environment variables, and volume mounts.
- Container process launch sequence. Trace how the runtime switches to the container rootfs, forks the container process, runs OCI hooks, and executes the image's command.
- Detached container monitoring handoff. Explain why the OCI runtime and Podman can exit while the detached container keeps running, and how Podman can later interact with it through conmon.
- Container exit and conmon response. Trace how an application exiting on its own or a user running podman stop leads to conmon receiving SIGCHLD and handling the container’s exit.
- Container cleanup and optional removal. Distinguish the network and mount cleanup performed by podman container cleanup from the additional container removal performed when --rm was specified.
What it builds on
- Rootless containers (chapter 1) · Introduces rootless containers.
- Podman is daemonless (chapter 1) · Introduces Podman's daemonless design.
- Pushing images (chapter 2) · The application image was previously pushed to a container registry.
- User-namespace support (chapter 1) · Introduces Podman’s user-namespace support.
- Volume mount options (chapter 3) · Discusses how user-namespace ownership mappings can affect container volumes.
- Storage drivers (chapter 5) · Storage drivers determine how container storage is mounted.
- Running pods (chapter 4) · The earlier description of conmon.
Section by section
Introduction
The introduction explains why rootless Podman is valuable on shared systems and sets up a closer look at how it works and where it can cause problems.
- Rootless workload security boundary: Explain why sharing a root-running container daemon is risky and why running each user's Podman workloads under that user's account is safer, especially if a container escapes.
Why it matters: The difference determines what an attacker could control after a container escape on a shared system. - Unprivileged applications and root-dependent images: Describe the distinction between privileged changes to the core Linux operating system and ordinary application work, and explain why images that require or initially use root complicate rootless operation.
Why it matters: It explains both why rootless containers are practical for many applications and why running existing images rootlessly can present problems.
Key terms: rootless mode, root-running daemon, container escape, root access, privileged mode, unprivileged mode, rootless, container images
6.1 How does rootless Podman work?
This section sets up a clean rootless Podman example and identifies user-namespace setup as the first step to examine behind the scenes.
- Initial user namespace setup: State that setting up the user namespace is the first thing Podman needs to do when running the rootless container in this example. Explain that the section introduces this step but leaves why and how it works for the next section.
Why it matters: This gives you a starting point for following the later breakdown of a rootless container run. - Clean storage and example run: Describe the example's setup: clear Podman's storage, then run a container using quay.io/rhatdan/myimage so Podman pulls the image from the registry and starts the myapp container on the host. State that podman rmi --all --force removes all images and containers from storage.
Why it matters: The fresh run provides the concrete example whose behind-the-scenes steps the chapter examines.
Key terms: rootless Podman, user namespace, podman rmi --all --force, quay.io/rhatdan/myimage, myapp, container registry
6.1.1 Images contain content owned by multiple user identifiers (UIDs)
This section explains how rootless Podman uses user and mount namespaces to handle images with multiple file owners while keeping container privileges separate from host root.
- Multiple image file owners: Explain why an image containing files owned by several UIDs poses a problem for a rootless user and why Podman needs a user namespace to handle it.
Why it matters: This is the reason rootless Podman needs more than an ordinary unprivileged process. - Subordinate UID mapping: Describe how Podman maps the user’s host UID to UID 0 inside its user namespace and maps additional inside UIDs to subordinate host UIDs listed in /etc/subuid and /etc/subgid. Explain how podman unshare and /proc/self/uid_map reveal that mapping.
Why it matters: The mapping explains how a container can see root and many file owners without granting its processes host-root identity. - Mapped ownership and access limits: Trace how a file’s owner appears inside versus outside the user namespace, and explain why being root inside it does not grant access to host files whose UIDs are unmapped.
Why it matters: It distinguishes a container’s apparent root privileges from access to files on the host. - Namespaced capability boundaries: Explain that root’s powers are divided into Linux capabilities and that capabilities held inside a user namespace, such as CAP_CHOWN and CAP_SETUID, operate only on mapped UIDs and GIDs. Describe why Podman also needs CAP_SYS_ADMIN to mount container filesystems.
Why it matters: It explains both how rootless Podman performs necessary setup and why those powers do not become unrestricted host privileges. - Isolated rootless filesystem mounts: Describe how a mount namespace confines Podman’s container mounts to a separate view of the filesystem and why it must be used alongside a user namespace. Explain that the kernel still restricts which filesystem types rootless processes may mount.
Why it matters: Mount isolation lets Podman assemble a container filesystem without changing the host’s mount view or handing out unrestricted mounting power.
Key terms: UID, GID, discretionary access control (DAC), image layers, user namespace, podman unshare, /proc/self/uid_map, /proc/self/gid_map, /etc/subuid, /etc/subgid
6.2 Rootless Podman under the covers
This section explains how rootless Podman establishes and keeps a user’s namespaces available across container runs, and how to refresh them when subordinate ID settings change.
- Rootless namespace startup: Trace how Podman’s first container run after login reads /etc/subuid and /etc/subgid, combines their entries with the user’s current UID and GID to create a user namespace, and launches the podman pause process to hold the user and mount namespaces open.
Why it matters: This explains why a Podman process may remain running after a container starts. - Shared rootless namespace: Explain that later Podman commands join the pause process’s namespaces to avoid namespace startup and shutdown races, and that a rootless user’s containers share one user namespace by default so they can share content and other namespaces.
Why it matters: The shared namespace explains both the lingering pause process and how a user’s containers can share resources. - Pause process lifecycle: Describe when the pause process goes away or is recreated, and explain why changes to /etc/subuid or /etc/subgid do not affect existing containers immediately: the pause process still holds the old namespace settings until podman system migrate removes it and it is restarted.
Why it matters: Refreshing the pause process lets changed subordinate ID settings take effect.
Key terms: /etc/subuid, /etc/subgid, UID/GID, user namespace, mount namespace, podman pause process, race conditions, sharing content, network namespace, podman system migrate
6.2.1 Pulling the image
This section traces how rootless Podman finds or pulls an image, stores its layers, and handles file ownership while unpacking them.
- Local image check and pull: Explain that Podman first checks local container storage for the image; if it is absent, Podman uses containers/image to contact the registry and pull the manifest, config, and layers.
Why it matters: The local check determines whether Podman needs to fetch an image before continuing container setup. - Ordered image layer storage: Describe how containers/storage reassembles the copied layers in order, creates each layer over the previous one in local container storage, and untars its contents.
Why it matters: An image's downloaded layers must be assembled into usable local storage. - Rootless layer ownership mapping: Explain that, while unpacking layers, containers/storage changes file ownership to the tarball's UIDs and GIDs using CAP_CHOWN in the user namespace, and that creating content fails if a specified UID or GID is not mapped there.
Why it matters: User-namespace mappings determine whether rootless Podman can recreate image files with their required ownership.
Key terms: local container storage, containers/image, manifest, layers, config, container registry, containers/storage, overlay mount point, storage layer, ~/.local/share/containers/storage
6.2.2 Creating a container
Podman records a new container, adds a writable layer above its image, and then moves on to network setup.
- Container creation and writable layer: Trace how Podman creates a container after the image and storage are ready: it adds the container to its internal database, asks containers/storage to create and mount writable disk space as a layer above the image, and then proceeds to network configuration.
Why it matters: This explains where a container’s writable space comes from before it starts running. - Rootless overlay mount selection: Distinguish how Podman mounts the writable layer: rootful containers default to native Linux overlay mounts, while rootless containers use native overlay on kernels with rootless overlay support and fuse-overlayfs on older kernels.
Why it matters: The mount method for a rootless container depends on kernel support.
Key terms: containers/storage, internal database, container layer, read/write layer, image, overlayfs, native overlay mounts, rootless overlay, fuse-overlayfs, overlay
6.2.3 Setting up the network
This section explains how rootless Podman uses slirp4netns to give containers network access and publish ports without permission to create host network devices or change firewall rules.
- Rootless networking constraints: Explain why rootless Podman uses slirp4netns instead of configuring container networking with CNI plugins. Distinguish permission to create a network namespace from permission to create network devices or change firewall rules.
Why it matters: The permission boundary explains both the need for user-mode networking and why more advanced setups require rootful containers. - User mode packet routing: Trace how slirp4netns connects a container’s network namespace to host networking, including the 8080:8080 port mapping, the TAP device, user-space packet handling, and host socket operations.
Why it matters: Following the packet path makes clear how a container can communicate over the network without privileged host-network configuration.
Key terms: rootless Podman, network namespace, slirp4netns, CNI plugins, rootful containers, 8080:8080 port mapping, TAP device, TCP/IP stack, host network namespace, socket operation
6.2.4 Starting the container monitor: conmon
Podman starts conmon to monitor a container, launch its configured OCI runtime, and arrange cleanup when the container exits.
- Conmon startup and cleanup: Trace how Podman starts conmon for a container, directs it to use the configured OCI runtime (usually crun or runc), and arranges for `podman container cleanup $CTRID` to run when the container exits.
Why it matters: This connects the container monitor to runtime launch and end-of-container cleanup.
Key terms: conmon, container monitor, OCI runtime, crun, runc, podman container cleanup $CTRID
6.2.5 Launching the OCI runtime
This section explains how the OCI runtime starts a rootless container and hands monitoring of the running process to conmon.
- OCI runtime kernel configuration: Explain how the OCI runtime reads the OCI spec file and prepares the kernel and container environment, including namespaces, cgroups v2, security settings, environment variables, and volume mounts.
Why it matters: These steps turn the container specification into an environment in which the process can run. - Container process launch sequence: Trace how the runtime switches to the container rootfs, forks the container process, runs OCI hooks, and executes the image's command.
Why it matters: This sequence explains how the prepared environment becomes a running container process. - Detached container monitoring handoff: Explain why the OCI runtime and Podman can exit while the detached container keeps running, and how Podman can later interact with it through conmon.
Why it matters: The handoff explains how a detached container remains manageable after its launching commands exit.
Key terms: OCI runtime, OCI spec file, namespaces, cgroups v2, SELinux label, seccomp rules, rootfs, container process, OCI hook programs, PID 1
6.2.6 The containerized application runs until completion
This subsection traces what happens when a containerized application exits, from conmon’s response to container cleanup and optional removal.
- Container exit and conmon response: Trace how an application exiting on its own or a user running podman stop leads to conmon receiving SIGCHLD and handling the container’s exit.
Why it matters: It explains how Podman handles a container after its application stops. - Container cleanup and optional removal: Distinguish the network and mount cleanup performed by podman container cleanup from the additional container removal performed when --rm was specified.
Why it matters: Stopping a container does not necessarily remove its stored layers and definition.
Key terms: podman stop, SIGCHLD, conmon, exit code, STDOUT/STDERR, podman container cleanup $CTRID, slirp4netns, mount points, --rm, containers/storage
6.3 Summary
The section recaps why rootless containers are more secure and names the namespaces and processes Podman uses to run them.
Where this is used later
- UID isolation: User namespace (chapter 10) · Examines the user-namespace isolation behind container UID boundaries.
- Restarting containers (chapter 7) · The distinction between rootless and rootful Podman
- Isolating containers using the - -userns=auto flag (chapter 10) · Container images can contain content owned by multiple UIDs.
- Rootless Podman with the - -userns=auto flag (chapter 10) · Provides the basic rootless user-namespace mapping that this section extends.
- User-namespaced Linux capabilities (chapter 10) · Examines user-namespaced Linux capabilities in more detail.
- Filesystem isolation: Mount namespace (chapter 10) · Examines filesystem isolation through mount namespaces.
- Containerized systemd requirements (chapter 7) · Podman creates and configures a container before its application starts.
- Network isolation: Network namespace (chapter 10) · The distinction between a network namespace and its network devices helps explain network isolation.
Concepts explained in this chapter
- user ID namespaceA user namespace is a Linux namespace that isolates security-related identifiers and capabilities and maps host user and group identifiers to namespace identifiers.
- mount namespaceA mount namespace is a Linux namespace that isolates the filesystem mount view available to a process group.
- Linux capabilityA Linux capability is a discrete permission that divides traditionally privileged root powers into independently controllable units.
- rootless modeA rootless container is a container whose engine and processes run without host-level root privileges.
- PodmanPodman is a daemonless container engine that runs containers and builds images, including under an unprivileged user account.
- rootful modeA rootful container is a container whose engine or processes run with host-level root privileges.
- Docker CLIThe Docker CLI is the command-line client through which users invoke Docker container operations.
- rootThe root user is the Unix-like operating-system account with unrestricted administrative authority over the host.
- network namespaceA network namespace is a Linux namespace that provides an isolated view of network devices and network configuration.
- containers/storageLocal container storage is the on-host storage managed by a container engine for container images and related container data.
- /etc/subgidThe /etc/subgid file assigns subordinate group-ID ranges to user accounts for user-namespace mappings.
- /etc/subuidThe /etc/subuid file assigns subordinate user-ID ranges to user accounts for user-namespace mappings.
- conmonconmon is a lightweight C program that monitors a container, manages attached I/O streams, and reports the container's exit status.
- image layerAn image layer is an immutable filesystem change set that contributes to a container image and can be stacked with other layers.
- root filesystemA root filesystem is the filesystem tree presented as the top-level directory hierarchy to an operating-system environment or container.
- storage driverA storage driver is a software component that implements the filesystem and metadata operations used to store container images and container filesystems.
- namespaced capabilityA namespaced capability is a Linux capability whose authority is limited to resources and identifiers within a user namespace.
- setuid bitSetuid is a Unix privilege mechanism that causes a process or executable operation to use a designated user identifier for access checks.
- Docker user groupThe Docker user group is a Unix group whose membership can grant users access to the Docker daemon socket, potentially providing host-root-equivalent control.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
