Container Management with Podman on CentOS/RHEL
Podman provides a daemonless container engine for developing, managing, and running OCI containers on CentOS/RHEL systems. This guide covers Podman's advanced features including rootless containers, pod management, and Kubernetes compatibility.
Podman Fundamentals
Understanding Podman Architecture
Podman's daemonless design:
# Install Podman
yum install -y podman podman-docker podman-compose
# Verify installation
podman version
podman info
# Podman components
# - podman: CLI tool for managing containers
# - buildah: Tool for building OCI container images
# - skopeo: Tool for working with remote image registries
# - runc: OCI container runtime
# Enable podman socket for Docker compatibility
systemctl enable --now podman.socket
# Test Docker compatibility
docker version # Using podman-docker alias
Basic Container Operations
Essential Podman commands:
# Search for images
podman search nginx
podman search --filter=is-official nginx
# Pull images
podman pull nginx:latest
podman pull registry.access.redhat.com/ubi8/ubi:latest
# List images
podman images
podman image ls --all
# Run containers
podman run -d --name webserver -p 8080:80 nginx
podman run -it --rm centos:8 /bin/bash
# Container management
podman ps
podman ps -a
podman logs webserver
podman exec -it webserver /bin/bash
podman stop webserver
podman start webserver
podman rm webserver
# Container inspection
podman inspect webserver
podman stats --no-stream
Rootless Containers
Configure Rootless Podman
Run containers without root privileges:
# Enable lingering for user
loginctl enable-linger $USER
# Configure subuid and subgid
sudo usermod --add-subuids 100000-165535 $USER
sudo usermod --add-subgids 100000-165535 $USER
# Verify configuration
podman unshare cat /proc/self/uid_map
podman system migrate
# Run rootless container
podman run -d --name rootless-nginx -p 8080:80 nginx
# Check container user namespace
podman exec rootless-nginx cat /proc/self/uid_map
# Configure storage for rootless
mkdir -p ~/.config/containers
cat > ~/.config/containers/storage.conf <<EOF
[storage]
driver = "overlay"
runroot = "/run/user/$(id -u)/containers"
graphroot = "/home/$USER/.local/share/containers/storage"
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"
EOF
Rootless Networking
Configure networking for rootless containers:
# Install slirp4netns for rootless networking
yum install slirp4netns
# Create rootless network
podman network create --driver bridge rootless-net
# Run container with custom network
podman run -d --name webapp \
--network rootless-net \
-p 8080:80 \
nginx
# Port forwarding for rootless containers
podman run -d --name app \
--publish 127.0.0.1:8080:80 \
--publish [::1]:8080:80 \
nginx
# Configure firewall for rootless containers
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Building Container Images
Using Dockerfile with Podman
Build images with Podman:
# Create Dockerfile
cat > Dockerfile <<EOF
FROM centos:8
LABEL maintainer="admin@example.com"
RUN yum update -y && \
yum install -y httpd && \
yum clean all
COPY index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
EOF
# Create content
echo "<h1>Hello from Podman</h1>" > index.html
# Build image
podman build -t myapp:latest .
podman build --no-cache -t myapp:v1.0 .
# Multi-stage build
cat > Dockerfile.multistage <<EOF
# Build stage
FROM golang:1.17 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# Runtime stage
FROM centos:8-minimal
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]
EOF
podman build -f Dockerfile.multistage -t myapp:slim .
Using Buildah
Advanced image building with Buildah:
# Install Buildah
yum install buildah
# Create container from scratch
container=$(buildah from scratch)
# Mount container filesystem
mountpoint=$(buildah mount $container)
# Install packages
yum install --installroot $mountpoint --releasever 8 \
--setopt install_weak_deps=false -y \
coreutils bash httpd
# Configure container
buildah config --cmd "/usr/sbin/httpd -D FOREGROUND" $container
buildah config --port 80 $container
buildah config --label maintainer="admin@example.com" $container
# Commit container
buildah commit $container myapp:buildah
# Unmount and remove working container
buildah umount $container
buildah rm $container
Pod Management
Creating and Managing Pods
Work with Podman pods:
# Create pod
podman pod create --name webapp-pod \
--publish 8080:80 \
--publish 3306:3306
# List pods
podman pod list
podman pod ps
# Add containers to pod
podman run -d --pod webapp-pod \
--name webapp-nginx \
nginx
podman run -d --pod webapp-pod \
--name webapp-mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:5.7
# Pod operations
podman pod start webapp-pod
podman pod stop webapp-pod
podman pod restart webapp-pod
podman pod logs webapp-pod
# Inspect pod
podman pod inspect webapp-pod
# Remove pod and containers
podman pod rm -f webapp-pod
Kubernetes YAML Generation
Generate Kubernetes manifests:
# Generate pod YAML
podman generate kube webapp-pod > webapp-pod.yaml
# Create pod from YAML
podman play kube webapp-pod.yaml
# Generate systemd unit files
podman generate systemd --new --name webapp-pod > webapp-pod.service
# Complex pod example
cat > complex-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
name: complex-app
spec:
containers:
- name: frontend
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
- name: backend
image: node:14
command: ["node", "server.js"]
ports:
- containerPort: 3000
volumeMounts:
- name: shared-data
mountPath: /app/data
volumes:
- name: shared-data
emptyDir: {}
EOF
podman play kube complex-pod.yaml
Container Orchestration
Systemd Integration
Manage containers with systemd:
# Create container with systemd integration
podman create --name systemd-nginx \
--systemd=true \
-p 8080:80 \
nginx
# Generate systemd service
podman generate systemd --new --name systemd-nginx \
> ~/.config/systemd/user/container-nginx.service
# Enable and start service
systemctl --user daemon-reload
systemctl --user enable container-nginx.service
systemctl --user start container-nginx.service
# Auto-update containers
cat > ~/.config/systemd/user/podman-auto-update.service <<EOF
[Unit]
Description=Podman auto-update service
Documentation=man:podman-auto-update(1)
[Service]
Type=oneshot
ExecStart=/usr/bin/podman auto-update
[Install]
WantedBy=multi-user.target
EOF
cat > ~/.config/systemd/user/podman-auto-update.timer <<EOF
[Unit]
Description=Podman auto-update timer
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
EOF
systemctl --user enable podman-auto-update.timer
Container Compose
Use podman-compose for multi-container apps:
# Install podman-compose
pip3 install podman-compose
# Create docker-compose.yml
cat > docker-compose.yml <<EOF
version: '3'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- app
app:
image: node:14
command: node server.js
working_dir: /app
volumes:
- ./app:/app
environment:
- NODE_ENV=production
- DB_HOST=db
db:
image: postgres:13
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
EOF
# Run with podman-compose
podman-compose up -d
podman-compose ps
podman-compose logs
podman-compose down
Storage Management
Volume Management
Work with Podman volumes:
# Create volumes
podman volume create webapp-data
podman volume create --opt size=10G large-data
# List volumes
podman volume ls
podman volume inspect webapp-data
# Use volumes in containers
podman run -d --name webapp \
-v webapp-data:/var/www/html \
-p 8080:80 \
nginx
# Backup volume
podman run --rm \
-v webapp-data:/source:ro \
-v $(pwd):/backup \
centos:8 \
tar czf /backup/webapp-data-backup.tar.gz -C /source .
# Restore volume
podman volume create webapp-data-restored
podman run --rm \
-v webapp-data-restored:/target \
-v $(pwd):/backup:ro \
centos:8 \
tar xzf /backup/webapp-data-backup.tar.gz -C /target
# Clean up volumes
podman volume prune
podman volume rm webapp-data
Advanced Storage Options
Configure storage drivers and options:
# Configure storage driver
cat > /etc/containers/storage.conf <<EOF
[storage]
driver = "overlay"
runroot = "/var/run/containers/storage"
graphroot = "/var/lib/containers/storage"
[storage.options]
additionalimagestores = [
"/var/lib/shared/overlay-images",
"/var/lib/shared/overlay-layers"
]
[storage.options.overlay]
mountopt = "nodev,metacopy=on"
EOF
# Use bind mounts with SELinux
podman run -d --name webapp \
-v /host/data:/container/data:Z \
-p 8080:80 \
nginx
# Named volumes with options
podman volume create --opt type=nfs \
--opt o=addr=nfs-server.example.com,rw \
--opt device=:/exports/data \
nfs-volume
Network Configuration
Advanced Networking
Configure container networking:
# Create custom networks
podman network create --driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
--ip-range 172.20.240.0/20 \
custom-net
# Create macvlan network
podman network create -d macvlan \
--subnet 192.168.1.0/24 \
--gateway 192.168.1.1 \
-o parent=eth0 \
macvlan-net
# Connect container to multiple networks
podman run -d --name multi-net \
--network custom-net \
nginx
podman network connect macvlan-net multi-net
# Configure DNS
podman run -d --name webapp \
--dns 8.8.8.8 \
--dns-search example.com \
--add-host db-server:192.168.1.100 \
nginx
# Network aliases
podman run -d --name database \
--network custom-net \
--network-alias db \
--network-alias mysql \
mysql:5.7
Container Communication
Inter-container networking:
# Create pod with shared network
podman pod create --name app-pod \
--share net \
--publish 8080:80
# Add containers sharing localhost
podman run -d --pod app-pod \
--name frontend \
nginx
podman run -d --pod app-pod \
--name backend \
-e FRONTEND_URL=http://localhost:80 \
node:14
# Container-to-container communication
podman network create app-network
podman run -d --name api \
--network app-network \
--hostname api-server \
myapi:latest
podman run -d --name web \
--network app-network \
-e API_HOST=api-server \
myweb:latest
Security Features
Container Security
Implement security best practices:
# Run with security options
podman run -d --name secure-app \
--security-opt no-new-privileges \
--security-opt label=disable \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--read-only \
--tmpfs /tmp \
nginx
# User namespace mapping
podman run -d --name mapped-user \
--userns=keep-id \
--user 1000:1000 \
nginx
# SELinux contexts
podman run -d --name selinux-app \
--security-opt label=type:container_t \
--security-opt label=level:s0:c100,c200 \
nginx
# Seccomp profiles
podman run -d --name restricted-app \
--security-opt seccomp=/path/to/seccomp.json \
nginx
# AppArmor profiles (if available)
podman run -d --name apparmor-app \
--security-opt apparmor=custom-profile \
nginx
Image Security Scanning
Scan container images:
# Install skopeo
yum install skopeo
# Inspect remote images
skopeo inspect docker://docker.io/nginx:latest
# Copy images between registries
skopeo copy \
docker://docker.io/nginx:latest \
docker://myregistry.example.com/nginx:latest
# Vulnerability scanning with Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy image nginx:latest
# Scan with podman
podman image trust show nginx
Registry Management
Private Registry Setup
Deploy private container registry:
# Run registry container
podman run -d --name registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry:2
# Configure insecure registry
cat >> /etc/containers/registries.conf <<EOF
[[registry]]
location = "localhost:5000"
insecure = true
EOF
# Push to private registry
podman tag myapp:latest localhost:5000/myapp:latest
podman push localhost:5000/myapp:latest
# Pull from private registry
podman pull localhost:5000/myapp:latest
# Secure registry with TLS
mkdir -p certs
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout certs/domain.key -x509 -days 365 \
-out certs/domain.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=registry.example.com"
podman run -d --name secure-registry \
-p 443:443 \
-v $(pwd)/certs:/certs:ro \
-v registry-data:/var/lib/registry \
-e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2
Migration and Compatibility
Docker to Podman Migration
Migrate from Docker:
# Export Docker images
docker save -o images.tar $(docker images -q)
# Import to Podman
podman load -i images.tar
# Convert Docker Compose
pip3 install podman-compose
podman-compose up -d
# Alias docker to podman
alias docker=podman
# Socket compatibility
systemctl enable --now podman.socket
export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
# Migrate volumes
for vol in $(docker volume ls -q); do
docker run --rm -v $vol:/source:ro -v $(pwd):/backup alpine \
tar czf /backup/$vol.tar.gz -C /source .
podman volume create $vol
podman run --rm -v $vol:/target -v $(pwd):/backup:ro alpine \
tar xzf /backup/$vol.tar.gz -C /target
done
Monitoring and Troubleshooting
Container Monitoring
Monitor container performance:
# Real-time stats
podman stats
# Container health checks
podman run -d --name healthcheck-app \
--health-cmd="curl -f http://localhost/ || exit 1" \
--health-interval=30s \
--health-retries=3 \
--health-timeout=10s \
--health-start-period=40s \
nginx
# Check container health
podman healthcheck run healthcheck-app
podman inspect healthcheck-app --format='{{.State.Health.Status}}'
# Export metrics
podman system df
podman system info --format json
# Integration with monitoring tools
cat > /usr/local/bin/podman-exporter.sh <<'EOF'
#!/bin/bash
# Export Podman metrics for Prometheus
echo "# HELP podman_containers_total Total number of containers"
echo "# TYPE podman_containers_total gauge"
echo "podman_containers_total $(podman ps -aq | wc -l)"
echo "# HELP podman_containers_running Running containers"
echo "# TYPE podman_containers_running gauge"
echo "podman_containers_running $(podman ps -q | wc -l)"
echo "# HELP podman_images_total Total number of images"
echo "# TYPE podman_images_total gauge"
echo "podman_images_total $(podman images -q | wc -l)"
EOF
chmod +x /usr/local/bin/podman-exporter.sh
Troubleshooting
Debug container issues:
# Debug commands
podman logs --tail 50 -f container-name
podman events --since 1h
podman inspect container-name
# System cleanup
podman system prune -a
podman volume prune
podman image prune -a
# Reset Podman
podman system reset
# Debug networking
podman network inspect bridge
podman port container-name
nsenter -t $(podman inspect -f '{{.State.Pid}}' container-name) -n ip a
# Storage debugging
podman info --debug
podman system df -v
Best Practices
Production Guidelines
- Use rootless containers when possible for better security
- Implement health checks for all production containers
- Set resource limits to prevent resource exhaustion
- Use specific image tags instead of 'latest'
- Scan images for vulnerabilities before deployment
- Implement proper logging and monitoring
- Regular cleanup of unused resources
Container Management Script
#!/bin/bash
# Comprehensive container management script
echo "=== Podman Container Health Check ==="
# Check running containers
running_containers=$(podman ps -q | wc -l)
echo "Running containers: $running_containers"
# Check unhealthy containers
unhealthy=$(podman ps --filter health=unhealthy -q | wc -l)
if [ $unhealthy -gt 0 ]; then
echo "WARNING: $unhealthy unhealthy containers detected"
podman ps --filter health=unhealthy
fi
# Check disk usage
disk_usage=$(podman system df --format "{{.Type}}\t{{.Size}}" | grep Images | awk '{print $2}')
echo "Image storage usage: $disk_usage"
# Check for containers with high memory usage
podman stats --no-stream --format "table {{.Container}}\t{{.MemPerc}}" | \
awk '$2 > 80 {print "High memory usage:", $1, $2"%"}'
# Clean up stopped containers older than 24 hours
podman container prune -f --filter until=24h
echo "Container health check completed"
Conclusion
Podman provides a secure, daemonless container runtime perfect for CentOS/RHEL environments. Its compatibility with Docker, support for rootless containers, and integration with systemd make it an excellent choice for enterprise container deployments. Master these features to build robust, secure containerized applications.