コンテンツにスキップ

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

CommandDescription
podman pull IMAGEPull an image from a registry
podman imagesList local images
podman rmi IMAGERemove an image
podman run IMAGECreate and start a container
podman run -d IMAGERun container in detached (background) mode
podman run -it IMAGE bashRun container with interactive terminal
podman psList running containers
podman ps -aList all containers (including stopped)
podman start CONTAINERStart a stopped container
podman stop CONTAINERStop a running container
podman rm CONTAINERRemove a stopped container
podman exec -it CONTAINER bashOpen shell in running container
podman logs CONTAINERView container logs
podman logs -f CONTAINERFollow container logs
podman inspect CONTAINERShow detailed container info
podman statsLive resource usage for containers
podman top CONTAINERShow processes in container
podman cp SRC CONTAINER:DESTCopy files into a container
podman commit CONTAINER IMAGECreate image from container
podman build -t NAME .Build image from Dockerfile/Containerfile
podman push IMAGEPush image to registry
podman login REGISTRYLog in to a container registry
podman logout REGISTRYLog out from a registry
podman network lsList networks
podman network create NAMECreate a network
podman volume lsList volumes
podman volume create NAMECreate a named volume
podman system pruneRemove unused data
podman system infoDisplay system information

Pod Management

CommandDescription
podman pod create --name NAMECreate a new pod
podman pod create -p 8080:80 --name NAMECreate pod with port mapping
podman pod lsList all pods
podman pod start PODStart a pod and its containers
podman pod stop PODStop a pod and its containers
podman pod rm PODRemove a pod
podman pod inspect PODInspect pod details
podman pod stats PODResource stats for a pod
podman pod top PODProcesses in all pod containers
podman run --pod POD IMAGEAdd container to existing pod
podman generate kube PODGenerate Kubernetes YAML from pod
podman play kube pod.yamlCreate 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

PracticeDetails
Always use rootlessRun containers as your user — no sudo podman needed
Use named volumesPrefer podman volume create over bind mounts for data persistence
Set :z or :Z on mountsRequired for SELinux systems to relabel bind-mounted directories
Pin image digestsUse image@sha256:... in production to prevent supply-chain drift
Use Quadlet for servicesPrefer .container files over generated systemd units for maintainability
Enable auto-updateUse io.containers.autoupdate=registry label with the systemd timer
Audit with podman diffCheck what changed inside a running container before committing
Health checksAdd HEALTHCHECK in Containerfile or --health-cmd at runtime
Resource limitsUse --memory, --cpus, --pids-limit to prevent runaway containers
Read-only rootUse --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