Podman Cheat Sheet
Overview
Podman is a daemonless container engine developed by Red Hat that provides a Docker-compatible command-line interface while offering significant security and architectural improvements. Unlike Docker, Podman does not require a privileged daemon process running as root, instead forking child processes to manage containers directly. This architecture enables rootless containers — containers running entirely within a user’s namespace without any elevated privileges — dramatically reducing the attack surface compared to traditional container runtimes.
Podman is fully OCI (Open Container Initiative) compliant, meaning it works with images built by Docker, Buildah, or any other OCI-compatible tool. The CLI is intentionally designed to be a drop-in replacement for Docker: most docker commands work identically with podman, and many users alias docker to podman without issue. Podman also introduces the concept of pods borrowed from Kubernetes — groups of containers sharing network namespaces — making it easier to develop and test Kubernetes workloads locally.
Systemd integration is a first-class feature. Podman can generate systemd unit files for containers and pods, and the newer Quadlet system (Podman 4.4+) allows declarative container definitions using .container files that systemd understands natively. This makes Podman an excellent choice for running containers as system services on Linux without Kubernetes overhead.
Installation
Ubuntu/Debian
# Install from official repos (Ubuntu 22.04+)
sudo apt update && sudo apt install -y podman
# Install newer version via Kubic repository
. /etc/os-release
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${VERSION_ID}/ /" \
| sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list
curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${VERSION_ID}/Release.key" \
| sudo apt-key add -
sudo apt update && sudo apt install -y podman
# Verify installation
podman --version
podman info
RHEL/CentOS/Fedora
# Fedora (included by default)
sudo dnf install -y podman
# RHEL 8/9
sudo dnf install -y container-tools
# Enable rootless support (may need subuids/subgids)
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 $USER
podman system migrate
macOS
# Install via Homebrew
brew install podman
# Initialize and start the Podman machine (VM)
podman machine init
podman machine start
# Verify
podman info
Docker Compose Compatibility
# Install podman-compose
pip3 install podman-compose
# Or use docker-compose with Podman socket
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker-compose up -d
Configuration
Rootless Setup
# Verify subuid/subgid ranges
cat /etc/subuid | grep $USER
cat /etc/subgid | grep $USER
# Add ranges if missing
sudo usermod --add-subuids 100000-165535 $USER
sudo usermod --add-subgids 100000-165535 $USER
# Migrate storage after changes
podman system migrate
# Check rootless info
podman unshare cat /proc/self/uid_map
Storage Configuration (~/.config/containers/storage.conf)
[storage]
driver = "overlay"
runroot = "/run/user/1000/containers"
graphroot = "/home/user/.local/share/containers/storage"
[storage.options]
pull_options = {enable_partial_images = "false", use_hard_links = "false", ostree_repos=""}
[storage.options.overlay]
mountopt = "nodev,metacopy=on"
Registries (/etc/containers/registries.conf)
[registries.search]
registries = ['docker.io', 'quay.io', 'registry.fedoraproject.org']
[registries.insecure]
registries = ['localhost:5000']
[registries.block]
registries = []
Alias Docker to Podman
# Add to ~/.bashrc or ~/.zshrc
alias docker=podman
alias docker-compose=podman-compose
# Or install the compatibility package
sudo apt install podman-docker # Debian/Ubuntu
sudo dnf install podman-docker # Fedora/RHEL
Core Commands
| Command | Description |
|---|---|
podman pull IMAGE | Pull an image from a registry |
podman images | List local images |
podman rmi IMAGE | Remove an image |
podman run IMAGE | Create and start a container |
podman run -d IMAGE | Run container in detached (background) mode |
podman run -it IMAGE bash | Run container with interactive terminal |
podman ps | List running containers |
podman ps -a | List all containers (including stopped) |
podman start CONTAINER | Start a stopped container |
podman stop CONTAINER | Stop a running container |
podman rm CONTAINER | Remove a stopped container |
podman exec -it CONTAINER bash | Open shell in running container |
podman logs CONTAINER | View container logs |
podman logs -f CONTAINER | Follow container logs |
podman inspect CONTAINER | Show detailed container info |
podman stats | Live resource usage for containers |
podman top CONTAINER | Show processes in container |
podman cp SRC CONTAINER:DEST | Copy files into a container |
podman commit CONTAINER IMAGE | Create image from container |
podman build -t NAME . | Build image from Dockerfile/Containerfile |
podman push IMAGE | Push image to registry |
podman login REGISTRY | Log in to a container registry |
podman logout REGISTRY | Log out from a registry |
podman network ls | List networks |
podman network create NAME | Create a network |
podman volume ls | List volumes |
podman volume create NAME | Create a named volume |
podman system prune | Remove unused data |
podman system info | Display system information |
Pod Management
| Command | Description |
|---|---|
podman pod create --name NAME | Create a new pod |
podman pod create -p 8080:80 --name NAME | Create pod with port mapping |
podman pod ls | List all pods |
podman pod start POD | Start a pod and its containers |
podman pod stop POD | Stop a pod and its containers |
podman pod rm POD | Remove a pod |
podman pod inspect POD | Inspect pod details |
podman pod stats POD | Resource stats for a pod |
podman pod top POD | Processes in all pod containers |
podman run --pod POD IMAGE | Add container to existing pod |
podman generate kube POD | Generate Kubernetes YAML from pod |
podman play kube pod.yaml | Create pod from Kubernetes YAML |
Advanced Usage
Running Containers with Security Options
# Rootless container with read-only filesystem
podman run --read-only --tmpfs /tmp -v data:/data:ro nginx
# Run with specific user namespace
podman run --userns=keep-id -v $HOME/app:/app myimage
# Drop all capabilities, add only what's needed
podman run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
# Run with custom seccomp profile
podman run --security-opt seccomp=/path/to/profile.json myimage
# Run with SELinux label
podman run --security-opt label=type:container_t myimage
# No new privileges escalation
podman run --security-opt no-new-privileges myimage
Volume and Bind Mounts
# Named volume
podman run -v myvolume:/data myimage
# Bind mount with SELinux relabeling
podman run -v /host/path:/container/path:z myimage # shared label
podman run -v /host/path:/container/path:Z myimage # private label
# Read-only bind mount
podman run -v /host/path:/container/path:ro myimage
# tmpfs mount
podman run --tmpfs /tmp:rw,size=100m myimage
Networking
# Create custom bridge network
podman network create --subnet 10.89.0.0/24 mynet
# Run container on custom network
podman run --network mynet myimage
# Expose ports
podman run -p 127.0.0.1:8080:80 nginx
# Rootless port forwarding (ports < 1024)
# Set sysctl or use slirp4netns
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
podman run -p 80:80 nginx
# Host network (Linux only)
podman run --network host myimage
# Inspect network
podman network inspect mynet
Building Images
# Build from Containerfile (Dockerfile equivalent)
podman build -t myapp:latest .
# Multi-stage build
podman build --target production -t myapp:prod .
# Build with build args
podman build --build-arg VERSION=1.2.3 -t myapp .
# Build without cache
podman build --no-cache -t myapp .
# Build from URL
podman build -t myapp https://github.com/user/repo.git
# Tag and push
podman tag myapp:latest registry.example.com/myapp:latest
podman push registry.example.com/myapp:latest
Generating Systemd Units
# Generate unit file for a container
podman generate systemd --name mycontainer --files --new
# Generate unit file for a pod
podman generate systemd --name mypod --files --new
# Install and enable the service
cp container-mycontainer.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now container-mycontainer
Quadlet Files (Podman 4.4+)
Create ~/.config/containers/systemd/myapp.container:
[Unit]
Description=My Application Container
After=network-online.target
[Container]
Image=docker.io/nginx:latest
PublishPort=8080:80
Volume=mydata:/usr/share/nginx/html:z
Environment=NGINX_HOST=example.com
Network=mynet.network
[Service]
Restart=always
TimeoutStartSec=900
[Install]
WantedBy=default.target
# Reload and start Quadlet service
systemctl --user daemon-reload
systemctl --user start myapp
# Check status
systemctl --user status myapp
journalctl --user -u myapp -f
Kubernetes Integration
# Generate Kubernetes YAML from a running pod
podman pod create --name webpod -p 8080:80
podman run --pod webpod -d nginx
podman generate kube webpod > webpod.yaml
# Apply Kubernetes YAML with Podman
podman play kube webpod.yaml
# Stop and remove resources from YAML
podman play kube --down webpod.yaml
# Export pod to Kubernetes format with volumes
podman generate kube --service webpod > webpod-with-service.yaml
Common Workflows
Development Container Workflow
# Run a development environment with live code mount
podman run -it --rm \
-v $(pwd):/app:z \
-w /app \
-p 3000:3000 \
--name devenv \
node:18 bash
# Use a pod for multi-service dev stack
podman pod create --name devstack -p 5432:5432 -p 6379:6379 -p 3000:3000
podman run -d --pod devstack \
-e POSTGRES_PASSWORD=secret \
--name postgres postgres:15
podman run -d --pod devstack \
--name redis redis:7
podman run -d --pod devstack \
-v $(pwd):/app:z \
--name app myapp:dev
Rootless Service Deployment
# Enable lingering so user services persist after logout
loginctl enable-linger $USER
# Create Quadlet service
mkdir -p ~/.config/containers/systemd/
cat > ~/.config/containers/systemd/webapp.container << 'EOF'
[Container]
Image=docker.io/nginx:latest
PublishPort=8080:80
Volume=%h/www:/usr/share/nginx/html:z
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now webapp
Auto-Update Containers
# Label containers for auto-update
podman run -d \
--label "io.containers.autoupdate=registry" \
--name myapp \
myimage:latest
# Run auto-update manually
podman auto-update
# Enable systemd timer for auto-updates
systemctl --user enable --now podman-auto-update.timer
Migrating from Docker
# Export Docker image and import into Podman
docker save myimage:latest | podman load
# Use existing Docker Compose files
podman-compose up -d
# Point Docker CLI at Podman socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
# Clean up all Podman resources
podman system prune -a --volumes
Tips and Best Practices
| Practice | Details |
|---|---|
| Always use rootless | Run containers as your user — no sudo podman needed |
| Use named volumes | Prefer podman volume create over bind mounts for data persistence |
Set :z or :Z on mounts | Required for SELinux systems to relabel bind-mounted directories |
| Pin image digests | Use image@sha256:... in production to prevent supply-chain drift |
| Use Quadlet for services | Prefer .container files over generated systemd units for maintainability |
| Enable auto-update | Use io.containers.autoupdate=registry label with the systemd timer |
Audit with podman diff | Check what changed inside a running container before committing |
| Health checks | Add HEALTHCHECK in Containerfile or --health-cmd at runtime |
| Resource limits | Use --memory, --cpus, --pids-limit to prevent runaway containers |
| Read-only root | Use --read-only with --tmpfs /tmp for hardened containers |
# Useful debugging commands
podman inspect --format '{{.NetworkSettings.IPAddress}}' CONTAINER
podman diff CONTAINER # Show filesystem changes
podman mount CONTAINER # Mount container filesystem
podman unshare ls /proc/self/uid_map # Debug user namespaces
podman system df # Show disk usage
podman healthcheck run CONTAINER # Run health check manually