621 lines
11 KiB
Markdown
621 lines
11 KiB
Markdown
# Podman (OCI Container) Guide
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
podman build -t argparse-builder .
|
|
```
|
|
|
|
### Using Containerfile
|
|
|
|
```bash
|
|
podman build -f Containerfile -t argparse-builder .
|
|
```
|
|
|
|
### Multi-architecture
|
|
|
|
```bash
|
|
podman build --platform linux/amd64,linux/arm64 -t argparse-builder --manifest argparse-builder .
|
|
```
|
|
|
|
### Build with cache
|
|
|
|
```bash
|
|
podman build --layers -t argparse-builder .
|
|
```
|
|
|
|
## Rootless Operation
|
|
|
|
### Setup Rootless Podman
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Container process
|
|
podman top <container> label
|
|
|
|
# Volume labels
|
|
ls -Z ./data
|
|
```
|
|
|
|
### SELinux Troubleshooting
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```ini
|
|
# ~/.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)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
podman generate systemd --new --name argparse-pod > argparse-pod.service
|
|
```
|
|
|
|
## Security Hardening
|
|
|
|
### Read-only Root
|
|
|
|
```bash
|
|
podman run -d -p 8080:8080 --read-only argparse-builder
|
|
```
|
|
|
|
### No New Privileges
|
|
|
|
```bash
|
|
podman run -d -p 8080:8080 --security-opt=no-new-privileges argparse-builder
|
|
```
|
|
|
|
### Drop Capabilities
|
|
|
|
```bash
|
|
podman run -d -p 8080:8080 --cap-drop=ALL argparse-builder
|
|
```
|
|
|
|
### Resource Limits
|
|
|
|
```bash
|
|
podman run -d -p 8080:8080 \
|
|
--memory=128m \
|
|
--cpus=0.5 \
|
|
--pids-limit=100 \
|
|
argparse-builder
|
|
```
|
|
|
|
### Combined Hardening
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
podman run -d -p 8080:8080 --tmpfs /tmp:rw,size=64m,mode=1777 argparse-builder
|
|
```
|
|
|
|
## Health and Monitoring
|
|
|
|
### Health Check
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Full inspect
|
|
podman inspect argparse-builder
|
|
|
|
# Specific field
|
|
podman inspect --format='{{.State.Health.Status}}' argparse-builder
|
|
```
|
|
|
|
## Registry Operations
|
|
|
|
### Login
|
|
|
|
```bash
|
|
# Docker Hub
|
|
podman login docker.io
|
|
|
|
# GitHub Container Registry
|
|
podman login ghcr.io
|
|
|
|
# Private registry
|
|
podman login registry.example.com
|
|
```
|
|
|
|
### Tag and Push
|
|
|
|
```bash
|
|
# Tag
|
|
podman tag argparse-builder ghcr.io/username/argparse-builder:latest
|
|
|
|
# Push
|
|
podman push ghcr.io/username/argparse-builder:latest
|
|
```
|
|
|
|
### Pull
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
pip3 install podman-compose
|
|
```
|
|
|
|
### podman-compose.yml
|
|
|
|
```yaml
|
|
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
|
|
|
|
```bash
|
|
podman-compose up -d
|
|
podman-compose logs -f
|
|
podman-compose down
|
|
```
|
|
|
|
## Kubernetes with Podman
|
|
|
|
### Generate K8s YAML
|
|
|
|
```bash
|
|
# From container
|
|
podman generate kube argparse-builder > argparse-k8s.yaml
|
|
|
|
# From pod
|
|
podman generate kube argparse-pod > argparse-pod-k8s.yaml
|
|
```
|
|
|
|
### Play Kubernetes YAML
|
|
|
|
```bash
|
|
# Create from YAML
|
|
podman play kube argparse-k8s.yaml
|
|
|
|
# Remove
|
|
podman play kube --down argparse-k8s.yaml
|
|
```
|
|
|
|
## Migration from Docker
|
|
|
|
### Pull Docker Images
|
|
|
|
```bash
|
|
podman pull docker.io/library/nginx
|
|
```
|
|
|
|
### Docker Compatibility
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Most docker-compose files work with podman-compose
|
|
podman-compose -f docker-compose.yml up
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Permission Denied (Rootless)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# Find what's using port
|
|
ss -tulpn | grep 8080
|
|
|
|
# Use different port
|
|
podman run -d -p 8081:8080 argparse-builder
|
|
```
|
|
|
|
### Storage Issues
|
|
|
|
```bash
|
|
# Check storage
|
|
podman system df
|
|
|
|
# Clean up
|
|
podman system prune -a
|
|
|
|
# Reset storage
|
|
podman system reset
|
|
```
|
|
|
|
## Performance Tuning
|
|
|
|
### Storage Driver
|
|
|
|
```bash
|
|
# Check current driver
|
|
podman info --format '{{.Store.GraphDriverName}}'
|
|
|
|
# Use overlay (default, best performance)
|
|
# Already configured in /etc/containers/storage.conf
|
|
```
|
|
|
|
### Network Performance
|
|
|
|
```bash
|
|
# Use host network (best performance, less isolation)
|
|
podman run -d --network host argparse-builder
|
|
```
|
|
|
|
### Build Cache
|
|
|
|
```bash
|
|
# Use buildah cache
|
|
podman build --layers -t argparse-builder .
|
|
```
|
|
|
|
## CI/CD Integration
|
|
|
|
### GitLab CI
|
|
|
|
```yaml
|
|
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
|
|
|
|
```yaml
|
|
- 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
|
|
|
|
1. **Use Rootless** - Run as regular user by default
|
|
2. **SELinux** - Keep enabled, use :Z/:z for volumes
|
|
3. **Systemd** - Use `podman generate systemd` for services
|
|
4. **Security** - Use `--read-only`, `--cap-drop=ALL`, labels
|
|
5. **OCI** - Use Containerfile (compatible with Dockerfile)
|
|
6. **Pods** - Group related containers in pods
|
|
7. **Health Checks** - Include in Containerfile
|
|
8. **Resources** - Set limits with `--memory`, `--cpus`
|
|
|
|
## Quick Reference
|
|
|
|
```bash
|
|
# 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
|
|
```
|