Run Containers Rootlessly with Podman: A Step‑by‑Step Guide
Learn how to launch Podman containers as a non‑root user, verify isolation, and recover from common issues. This guide covers prerequisites, a concrete example, and practical engineering decisions for secure, daemonless container execution.
05 Jul 2025, 20:40 UTC

Desired Outcome
The goal is to execute Podman containers as a regular user without root privileges, leveraging user namespaces for isolation. This approach reduces the attack surface, satisfies least‑privilege compliance, and allows multi‑tenant workloads on shared hosts.
Prerequisites
- Linux kernel 4.18+ with user namespace support.
- Subordinate UID/GID ranges defined in
/etc/subuidand/etc/subgid(default 65536 IDs per user). - Podman 3.0 or newer installed and in
$PATH. - Optional but recommended: an active systemd user session for
systemctl --userintegration.
Procedure
- Verify subuid/subgid entries for the current user.
grep ^$(whoami): /etc/subuid grep ^$(whoami): /etc/subgid - Pull an image from Docker Hub or another registry.
podman pull docker.io/library/alpine:latest - Run a rootless container and test isolation.
podman run --rm alpine:latest echo hello - Inspect internal UID mapping to confirm non‑root execution.
cid=$(podman run -d --rm alpine:latest sleep 30) podman exec $cid idThe output should show
uid=1000(or the mapped UID), notuid=0. - Set up a persistent workload with systemd (optional but recommended for long‑running services).
podman generate systemd --name myapp --new --files # Copy the generated unit to the user systemd directory cp container-myapp.service ~/.config/systemd/user/ # Reload and enable the service systemctl --user daemon-reload systemctl --user enable --now container-myapp.service
Expected Checks
- Run
podman info --format jsonand confirmhost.security.rootlessis true. - Execute
podman exec <cid> idinside a running container; the UID should match the host user. - Check
/proc/<pid>/uid_mapfor the container process to see the namespace mapping. - Verify no root processes are spawned on the host:
ps -ef | grep <cid>should list the user. - If exposing ports, remember that rootless networking defaults to ports >1024. For lower ports, adjust
net.ipv4.ip_unprivileged_port_start(requires root) or usepodman portforwarding.
Recovery Options
- Subordinate ID exhaustion: Append a new range to
/etc/subuidand/etc/subgid, then log out and back in. - Permission errors on volumes: Use
podman unshareto adjust ownership.podman unshare chown -R 1000:1000 /path/to/volume - SELinux/AppArmor labeling issues: Ensure the container image and runtime are labeled correctly. Use
podman run --security-opt label=disablefor testing, but avoid in production. - Corrupted storage:
podman system resetremoves all local data. Use with caution.
Practical Engineering Decision
Rootless Podman is preferable over rootful Docker for environments where security, compliance, and minimal privileges are paramount—such as CI/CD agents, developer laptops, and edge devices. Its daemonless architecture eliminates a single point of failure, and systemd user integration provides robust lifecycle management without requiring a system‑wide service. For multi‑container applications, podman-compose offers a Docker‑compose‑compatible experience without a daemon.
When deploying at scale, consider configuring net.ipv4.ip_unprivileged_port_start to lower the port threshold if the host requires binding to well‑known ports, but remember this change requires root and may affect other services.
Overall, rootless Podman delivers a secure, flexible container runtime that aligns with modern DevOps and DevSecOps practices.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.