11 KiB
11 KiB
Podman (OCI Container) Guide
Quick Start
# Build
podman build -t argparse-builder .
# Run rootless
podman run -d -p 8080:8080 argparse-builder
# Run with SELinux
podman run -d -p 8080:8080 --security-opt label=type:container_t argparse-builder
Podman vs Docker
Feature | Podman | Docker |
---|---|---|
Daemon | Daemonless | Requires daemon |
Root | Rootless by default | Needs root/group |
SELinux | Native support | Additional config |
Systemd | Native integration | Third-party |
OCI | Full compliance | Mostly compliant |
Build Commands
Standard Build
podman build -t argparse-builder .
Using Containerfile
podman build -f Containerfile -t argparse-builder .
Multi-architecture
podman build --platform linux/amd64,linux/arm64 -t argparse-builder --manifest argparse-builder .
Build with cache
podman build --layers -t argparse-builder .
Rootless Operation
Setup Rootless Podman
# Install
sudo dnf install podman
# Configure subuid/subgid (automatic on most systems)
grep $(whoami) /etc/subuid
grep $(whoami) /etc/subgid
# Run rootless
podman run -d -p 8080:8080 argparse-builder
# Verify
podman ps
Port Binding < 1024 (Rootless)
# Option 1: Use high port and forward
podman run -d -p 8080:8080 argparse-builder
sudo firewall-cmd --add-forward-port=port=80:proto=tcp:toport=8080
# Option 2: Set sysctl
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
# Option 3: Use systemd socket activation
# See systemd section below
SELinux Configuration
Run with SELinux
# Default (uses process label)
podman run -d -p 8080:8080 argparse-builder
# Specific label
podman run -d -p 8080:8080 --security-opt label=type:container_t argparse-builder
# Disable SELinux for container (not recommended)
podman run -d -p 8080:8080 --security-opt label=disable argparse-builder
Volume Mounts with SELinux
# Auto-label volume (recommended)
podman run -d -p 8080:8080 -v ./data:/data:Z argparse-builder
# Shared label (multiple containers)
podman run -d -p 8080:8080 -v ./data:/data:z argparse-builder
# Private label (single container)
podman run -d -p 8080:8080 -v ./data:/data:Z argparse-builder
Check SELinux Context
# Container process
podman top <container> label
# Volume labels
ls -Z ./data
SELinux Troubleshooting
# Check denials
sudo ausearch -m avc -ts recent
# Generate policy
sudo ausearch -m avc | audit2allow -M my-argparse
sudo semodule -i my-argparse.pp
# Check booleans
getsebool -a | grep container
Systemd Integration
Generate Systemd Unit
# Create container
podman run -d --name argparse-builder -p 8080:8080 argparse-builder
# Generate unit file
podman generate systemd --new --name argparse-builder > ~/.config/systemd/user/argparse-builder.service
# Enable and start
systemctl --user daemon-reload
systemctl --user enable --now argparse-builder
Systemd Unit (Manual)
# ~/.config/systemd/user/argparse-builder.service
[Unit]
Description=Argparse Builder Container
Wants=network-online.target
After=network-online.target
[Service]
Restart=always
ExecStartPre=/usr/bin/podman pull argparse-builder:latest
ExecStart=/usr/bin/podman run \
--rm \
--name argparse-builder \
-p 8080:8080 \
--security-opt label=type:container_t \
argparse-builder:latest
ExecStop=/usr/bin/podman stop -t 10 argparse-builder
ExecStopPost=/usr/bin/podman rm -f argparse-builder
[Install]
WantedBy=default.target
System-wide Service (requires root)
# Generate for system
sudo podman generate systemd --new --name argparse-builder > /etc/systemd/system/argparse-builder.service
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable --now argparse-builder
Pod Management
Create Pod
# Create pod with port mapping
podman pod create --name argparse-pod -p 8080:8080
# Run container in pod
podman run -d --pod argparse-pod argparse-builder
# List pods
podman pod ps
# Inspect pod
podman pod inspect argparse-pod
Pod with Multiple Containers
podman pod create --name argparse-stack -p 8080:8080 -p 9090:9090
# Application
podman run -d --pod argparse-stack argparse-builder
# Monitoring (example)
podman run -d --pod argparse-stack prom/prometheus
Pod Systemd Service
podman generate systemd --new --name argparse-pod > argparse-pod.service
Security Hardening
Read-only Root
podman run -d -p 8080:8080 --read-only argparse-builder
No New Privileges
podman run -d -p 8080:8080 --security-opt=no-new-privileges argparse-builder
Drop Capabilities
podman run -d -p 8080:8080 --cap-drop=ALL argparse-builder
Resource Limits
podman run -d -p 8080:8080 \
--memory=128m \
--cpus=0.5 \
--pids-limit=100 \
argparse-builder
Combined Hardening
podman run -d -p 8080:8080 \
--read-only \
--security-opt=no-new-privileges \
--cap-drop=ALL \
--security-opt label=type:container_t \
--memory=128m \
--cpus=0.5 \
argparse-builder
Networking
Port Mapping
# Basic
podman run -d -p 8080:8080 argparse-builder
# Different host port
podman run -d -p 3000:8080 argparse-builder
# Specific interface
podman run -d -p 127.0.0.1:8080:8080 argparse-builder
Custom Network
# Create network
podman network create argparse-net
# Run with network
podman run -d --network argparse-net -p 8080:8080 argparse-builder
# Inspect network
podman network inspect argparse-net
DNS
# Custom DNS
podman run -d -p 8080:8080 --dns=8.8.8.8 argparse-builder
# Add hosts
podman run -d -p 8080:8080 --add-host=api.local:192.168.1.100 argparse-builder
Storage and Volumes
Named Volume
# Create volume
podman volume create argparse-data
# Use volume with SELinux
podman run -d -p 8080:8080 -v argparse-data:/data:Z argparse-builder
# Inspect volume
podman volume inspect argparse-data
Bind Mount
# Auto-label (Z)
podman run -d -p 8080:8080 -v ./logs:/app/logs:Z argparse-builder
# Shared label (z) - multiple containers
podman run -d -p 8080:8080 -v ./shared:/shared:z argparse-builder
tmpfs Mount
podman run -d -p 8080:8080 --tmpfs /tmp:rw,size=64m,mode=1777 argparse-builder
Health and Monitoring
Health Check
# Check health status
podman healthcheck run argparse-builder
# View logs
podman logs argparse-builder
# Stats
podman stats argparse-builder
# Top processes
podman top argparse-builder
Inspect Container
# Full inspect
podman inspect argparse-builder
# Specific field
podman inspect --format='{{.State.Health.Status}}' argparse-builder
Registry Operations
Login
# Docker Hub
podman login docker.io
# GitHub Container Registry
podman login ghcr.io
# Private registry
podman login registry.example.com
Tag and Push
# Tag
podman tag argparse-builder ghcr.io/username/argparse-builder:latest
# Push
podman push ghcr.io/username/argparse-builder:latest
Pull
# Pull image
podman pull ghcr.io/username/argparse-builder:latest
# Pull specific platform
podman pull --platform linux/arm64 ghcr.io/username/argparse-builder:latest
Podman Compose
Install
pip3 install podman-compose
podman-compose.yml
version: "3"
services:
argparse-builder:
build: .
ports:
- "8080:8080"
restart: unless-stopped
security_opt:
- label=type:container_t
- no-new-privileges
read_only: true
cap_drop:
- ALL
resources:
limits:
cpus: "0.5"
memory: 128M
Usage
podman-compose up -d
podman-compose logs -f
podman-compose down
Kubernetes with Podman
Generate K8s YAML
# From container
podman generate kube argparse-builder > argparse-k8s.yaml
# From pod
podman generate kube argparse-pod > argparse-pod-k8s.yaml
Play Kubernetes YAML
# Create from YAML
podman play kube argparse-k8s.yaml
# Remove
podman play kube --down argparse-k8s.yaml
Migration from Docker
Pull Docker Images
podman pull docker.io/library/nginx
Docker Compatibility
# Use docker command (alias)
alias docker=podman
# Docker socket emulation
podman system service --time=0 unix:///tmp/podman.sock
export DOCKER_HOST=unix:///tmp/podman.sock
Convert docker-compose
# Most docker-compose files work with podman-compose
podman-compose -f docker-compose.yml up
Troubleshooting
Permission Denied (Rootless)
# Check subuid/subgid
grep $(whoami) /etc/subuid /etc/subgid
# Verify user namespaces
podman unshare cat /proc/self/uid_map
# Reset storage
podman system reset
SELinux Denials
# Check denials
sudo ausearch -m avc -ts recent | grep podman
# Temporary permissive mode (troubleshooting)
sudo setenforce 0
# Re-enable
sudo setenforce 1
Port Already in Use
# Find what's using port
ss -tulpn | grep 8080
# Use different port
podman run -d -p 8081:8080 argparse-builder
Storage Issues
# Check storage
podman system df
# Clean up
podman system prune -a
# Reset storage
podman system reset
Performance Tuning
Storage Driver
# Check current driver
podman info --format '{{.Store.GraphDriverName}}'
# Use overlay (default, best performance)
# Already configured in /etc/containers/storage.conf
Network Performance
# Use host network (best performance, less isolation)
podman run -d --network host argparse-builder
Build Cache
# Use buildah cache
podman build --layers -t argparse-builder .
CI/CD Integration
GitLab CI
build:
image: quay.io/podman/stable
services:
- podman:dind
script:
- podman build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- podman push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
GitHub Actions
- name: Build with Podman
run: |
podman build -t argparse-builder .
podman tag argparse-builder ghcr.io/${{ github.repository }}:latest
podman push ghcr.io/${{ github.repository }}:latest
Best Practices
- Use Rootless - Run as regular user by default
- SELinux - Keep enabled, use :Z/:z for volumes
- Systemd - Use
podman generate systemd
for services - Security - Use
--read-only
,--cap-drop=ALL
, labels - OCI - Use Containerfile (compatible with Dockerfile)
- Pods - Group related containers in pods
- Health Checks - Include in Containerfile
- Resources - Set limits with
--memory
,--cpus
Quick Reference
# Build
podman build -t name .
# Run
podman run -d -p 8080:8080 name
# SELinux volume
podman run -v ./data:/data:Z name
# Systemd
podman generate systemd --new name
# Rootless
podman run --userns=keep-id name
# Pod
podman pod create -p 8080:8080
podman run --pod podname name