Skip to content
Back to skills

Podman

ASecurity

Expert coverage of Podman across all supported versions: daemonless architecture, rootless containers, Quadlet systemd integration, pods, podman machine, Netavark networking, crun runtime, and Docker migration. Use when the question is about Podman itself (any OS) -- \"Podman\", \"podman-compose\", \"Quadlet\", \"rootless\", \"daemonless\", \"conmon\", \"Netavark\", \"podman machine\", \"podman generate kube\", \"podman kube play\". Do NOT use for RHEL-specific Podman packaging, SELinux integ...

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 24, 2026
devopsrustgobashnodedockerkubernetesapibackendperformance

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumUses curl or wget to download content

Pro scans all 4 files and shows the line behind each finding

Scanned September 24, 2026

npx -y skills add chrishuffman5/domain-expert --skill podman --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Podman?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Podman
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/chrishuffman5-podman/badge)](https://www.skillsdirectory.com/skills/chrishuffman5-podman)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: podman
description: "Expert coverage of Podman across all supported versions: daemonless architecture, rootless containers, Quadlet systemd integration, pods, podman machine, Netavark networking, crun runtime, and Docker migration. Use when the question is about Podman itself (any OS) -- \"Podman\", \"podman-compose\", \"Quadlet\", \"rootless\", \"daemonless\", \"conmon\", \"Netavark\", \"podman machine\", \"podman generate kube\", \"podman kube play\". Do NOT use for RHEL-specific Podman packaging, SELinux integration, or subscription-manager/dnf module questions -- that's the `rhel-podman` skill (in the `os` plugin)."
license: MIT
---

# Podman

This skill covers Podman across all supported versions (5.x through 6.0), including:

- Daemonless, fork/exec architecture (no central daemon)
- Rootless containers (user namespaces, sub-UID/GID mapping)
- Quadlet systemd integration (.container, .pod, .network, .volume files)
- Kubernetes-compatible pods and YAML generation
- Netavark networking stack with Aardvark-DNS
- crun OCI runtime (default, faster than runc)
- podman machine for macOS and Windows
- Docker CLI compatibility and migration patterns
- Auto-update with systemd timers

When a question is version-specific, read the matching file in the Version-specific guidance section below. When the version is unknown, provide guidance based on the latest stable release.

## How to Approach Tasks

1. **Classify** the request:
   - **Rootless setup** -- Load `references/best-practices.md` for sub-UID/GID, kernel requirements, networking
   - **Quadlet/systemd** -- Load `references/best-practices.md` for Quadlet patterns, unit file design
   - **Architecture** -- Load `references/architecture.md` for daemonless model, Netavark, conmon, storage
   - **Docker migration** -- Load `references/best-practices.md` for compatibility, differences, socket emulation
   - **Pod management** -- Apply K8s-compatible pod patterns

2. **Identify version** -- Determine Podman version. Key boundaries: v4.0 (Netavark), v5.0 (rewritten networking), v5.6 (Quadlet command suite), v5.8 (multi-file Quadlet), v6.0 (major API revision). If unclear, ask.

3. **Load context** -- Read the relevant reference file below.

4. **Analyze** -- Apply Podman-specific reasoning, not Docker advice. The daemonless model changes how containers are managed.

5. **Recommend** -- Provide actionable guidance with CLI examples and Quadlet configurations.

6. **Verify** -- Suggest validation steps (`podman inspect`, `systemctl status`, `podman healthcheck run`).

## Core Architecture: Daemonless Model

```
podman CLI --> fork/exec --> conmon --> crun/runc --> Linux kernel
                                 |
                          (conmon stays alive,
                           monitors container I/O,
                           captures exit code)
```

Each `podman` invocation is a direct fork/exec operation. There is no background daemon process. This means:

- **No single point of failure**: No daemon crash can bring down all containers
- **No root-owned socket**: No `/var/run/docker.sock` to protect (eliminates an entire class of privilege escalation attacks)
- **Containers are child processes**: Owned by the user or systemd, not a daemon
- **Better systemd integration**: Containers can be first-class systemd units via Quadlet
- **Compatible with sudo**: Run rootful or rootless without configuration changes

### Key Components

| Component | Role |
|---|---|
| libpod | Core Podman library (container and pod management) |
| conmon | Container monitor process; stays alive while container runs, captures stdout/stderr |
| crun | Default OCI runtime (C, 10x faster startup than runc) |
| Netavark | Network stack (replaced CNI plugins in Podman 4+) |
| Aardvark-DNS | DNS resolution within Podman networks |
| containers/image | Image transport library (registry, OCI dir, docker-archive, etc.) |
| containers/storage | Layer storage management (overlay, btrfs, zfs, vfs) |
| Buildah | Image build engine (integrated into `podman build`) |
| Skopeo | Image inspection and copy without pulling (separate tool, same ecosystem) |

## Rootless Containers

Podman's flagship capability. Containers run entirely within a user's namespace -- no root required anywhere in the stack.

### How It Works

User namespaces map container UIDs to unprivileged host UIDs:
```
Container UID 0 (root) --> Host UID 100000 (unprivileged)
Container UID 1     --> Host UID 100001
...
Container UID 65535 --> Host UID 165535
```

### Requirements

- Kernel 5.11+ (or older with `newuidmap`/`newgidmap` setuid binaries)
- `/etc/subuid` and `/etc/subgid` entries for the user:
  ```
  username:100000:65536
  ```
- `/proc/sys/kernel/unprivileged_userns_clone = 1` (some distros disable this)
- cgroup v2 with user delegation enabled

### Rootless Networking

Rootless containers cannot use raw sockets or modify host network configuration. Networking options:

| Backend | Performance | Notes |
|---|---|---|
| pasta (default in 5.x+) | Good | Uses network namespaces, better than slirp4netns |
| slirp4netns (legacy) | Moderate | Userspace TCP/IP stack, higher latency |
| host networking | Best | `--network host` shares host namespace |

### Rootless Limitations

- No ports < 1024 without `net.ipv4.ip_unprivileged_port_start=0`
- No macvlan/ipvlan network drivers
- No `--privileged` (maps to fake privileges within user namespace)
- Storage at `~/.local/share/containers/storage/` (different from rootful `/var/lib/containers/storage/`)
- Separate image and container stores for rootful vs rootless

### Rootless UID Mapping Modes

```bash
podman run --userns=keep-id myimage      # map current user into container as same UID
podman run --userns=auto myimage         # automatically assign sub-UID range
podman run --userns=host myimage         # no user namespace (rootful behavior)
```

`--userns=keep-id` is essential for bind mounts where the container needs to read/write files owned by the host user.

## Pods (Kubernetes-Compatible)

Podman's pod concept mirrors Kubernetes Pods: containers share a network namespace and optional PID namespace.

```bash
# Create pod with published ports (ports go on the pod, not individual containers)
podman pod create --name webapp -p 8080:80

# Add containers to the pod
podman run -d --pod webapp --name nginx nginx:latest
podman run -d --pod webapp --name sidecar my-sidecar:latest

# Containers share localhost within the pod (like K8s)
# nginx and sidecar can communicate via localhost

# Generate Kubernetes YAML from running pod
podman generate kube webapp > pod.yaml

# Deploy from Kubernetes YAML
podman kube play pod.yaml
podman kube play deployment.yaml    # supports Deployments, Services
podman kube down pod.yaml           # teardown
```

The **infra container** (pause container) holds the network namespace for the pod, identical to Kubernetes behavior.

## Quadlet (systemd Integration)

Quadlet is the production-grade pattern for running containers as systemd services. It converts declarative `.container` files into systemd `.service` units.

### How It Works

1. Place `.container`, `.pod`, `.network`, or `.volume` files in a watched directory
2. The Quadlet generator converts them to systemd `.service` units during `daemon-reload`
3. systemd manages the full container lifecycle

### File Locations

| Scope | Directory |
|---|---|
| System (root) | `/etc/containers/systemd/` |
| User (rootless) | `~/.config/containers/systemd/` |

### .container File

```ini
[Unit]
Description=My Application
After=network-online.target

[Container]
Image=registry.example.com/myapp:v2.0
ContainerName=myapp
PublishPort=8080:8080
Environment=NODE_ENV=production
EnvironmentFile=/etc/myapp/env
Volume=myapp-data.volume:/app/data:z
Network=myapp-net.network
HealthCmd=curl -f http://localhost:8080/health
HealthInterval=30s
ReadOnly=true
RunInit=true
AutoUpdate=registry

[Service]
Restart=on-failure
RestartSec=5s
TimeoutStartSec=60

[Install]
WantedBy=default.target
```

### Lifecycle

```bash
systemctl --user daemon-reload           # pick up new/changed Quadlet files
systemctl --user enable --now myapp      # start and enable at login
systemctl --user status myapp            # check status
journalctl --user -u myapp -f            # view logs
```

### Auto-Update

```bash
# Enable auto-update timer (checks for new images)
systemctl --user enable --now podman-auto-update.timer

# Manual update check
podman auto-update

# Container must have AutoUpdate=registry in Quadlet file
```

## Docker Compatibility

### CLI Compatibility

Most Docker CLI commands work with `podman` unchanged:
```bash
alias docker=podman        # works for most commands
podman run, exec, build, pull, push, images, ps, logs, inspect, stop, rm
```

### Docker Socket Emulation

```bash
# Enable Docker-compatible API socket (rootless)
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock

# Docker Compose works against Podman's socket
docker-compose up -d
```

### Key Differences from Docker

| Feature | Docker | Podman |
|---|---|---|
| Architecture | Daemon (dockerd) | Daemonless (fork/exec) |
| Default runtime | runc | crun (faster) |
| Root requirement | Daemon runs as root | Rootless by default |
| Pod support | No | Yes (K8s-compatible) |
| K8s YAML | No | `podman generate kube` / `podman kube play` |
| systemd integration | Restart policies only | Native (Quadlet) |
| Auto-update | No built-in | Built-in with Quadlet |
| Image signing | Docker Content Trust | Sigstore via containers/image |
| Swarm | Yes | No (use K8s instead) |
| Docker Compose | Native | Via socket emulation or podman-compose |

### SELinux Volume Labels

On SELinux-enabled systems (RHEL, Fedora), bind mounts require labels:
```bash
podman run -v /host/path:/container/path:z myimage   # shared label (multi-container)
podman run -v /host/path:/container/path:Z myimage   # private label (single container)
```

Omitting `:z` or `:Z` on SELinux systems causes "Permission denied" errors.

## Common Pitfalls

1. **Rootful vs rootless confusion**: Images, containers, and volumes are stored separately. `sudo podman images` shows different images than `podman images`.
2. **Missing sub-UID/GID entries**: Rootless fails silently or with cryptic errors if `/etc/subuid`/`/etc/subgid` are not configured.
3. **Port < 1024 in rootless**: Cannot bind without `net.ipv4.ip_unprivileged_port_start=0`.
4. **SELinux volume labels**: Forgetting `:z` or `:Z` on RHEL/Fedora causes permission denied errors.
5. **Docker Compose compatibility**: Some advanced Compose features (build secrets, watch mode) may not work via podman-compose. Use Docker socket emulation for better compatibility.
6. **podman machine resource defaults**: Default VM has limited CPU/memory. Increase via `podman machine init --cpus 4 --memory 8192`.
7. **Quadlet file location**: Must be in exact directories or systemd won't find them. Use `systemd-analyze verify` to check.

## Version-specific guidance

| Version | Reference | What's version-specific |
|---|---|---|
| 6.0 | `references/versions/6.0.md` | Major API revision, Quadlet enhancements |

## Reference Files

Read these for implementation depth:

- `references/architecture.md` -- Daemonless model, conmon, Netavark, Aardvark-DNS, rootless internals, storage. Read for "how does X work" questions.
- `references/best-practices.md` -- Rootless setup, Quadlet patterns, Docker migration, systemd integration. Read for design and operations questions.

Files in this skill

  • SKILL.md11.3 KB
  • references/architecture.md7.8 KB
  • references/best-practices.md8.5 KB
  • references/versions/6.0.md5.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…