Podman is a daemonless, open-source container engine designed to develop, manage, and run containers on Linux systems. Unlike Docker, Podman doesn’t require a central daemon and can run containers as a regular user without root privileges. This comprehensive guide will walk you through installing and using Podman on AlmaLinux, from basic commands to advanced features.
Table of Contents
- Understanding Podman
- Installing Podman on AlmaLinux
- Basic Podman Commands
- Working with Container Images
- Container Management
- Networking in Podman
- Volume Management
- Podman Compose
- Rootless Containers
- Systemd Integration
- Migration from Docker
- Security Features
- Advanced Features
- Troubleshooting
Understanding Podman
What is Podman?
Podman (Pod Manager) is a container management tool that’s part of the libpod library. It’s designed to be a drop-in replacement for Docker, with the key difference being its daemonless architecture.
Key Features
- Daemonless Architecture: No central daemon required
- Rootless Containers: Run containers without root privileges
- Pod Support: Native support for Kubernetes-style pods
- Docker Compatible: Uses the same command syntax as Docker
- OCI Compliant: Works with OCI (Open Container Initiative) containers
- Systemd Integration: Generate systemd services for containers
- Built-in Security: SELinux and seccomp support
Podman vs Docker
Feature | Podman | Docker |
---|---|---|
Architecture | Daemonless | Daemon-based |
Root requirement | Optional (rootless mode) | Required for daemon |
Process model | Fork/exec model | Client-server model |
systemd integration | Native | Limited |
Kubernetes compatibility | Native pod support | Through Docker Compose |
Security | Built-in rootless | Rootless mode available |
Installing Podman on AlmaLinux
Prerequisites
# Update system packages
sudo dnf update -y
# Check AlmaLinux version
cat /etc/almalinux-release
# Ensure SELinux is in enforcing mode (recommended)
getenforce
Installation Steps
# Install Podman and related tools
sudo dnf install -y podman podman-docker
# Install additional tools
sudo dnf install -y buildah skopeo
# Install container networking plugins
sudo dnf install -y containernetworking-plugins
# Verify installation
podman --version
podman info
Post-Installation Configuration
# Enable user namespaces for rootless containers
sudo sysctl user.max_user_namespaces=28633
echo "user.max_user_namespaces=28633" | sudo tee /etc/sysctl.d/userns.conf
# Configure registries
sudo nano /etc/containers/registries.conf
# Add trusted registries
unqualified-search-registries = ["docker.io", "quay.io", "registry.fedoraproject.org"]
# Configure storage
sudo nano /etc/containers/storage.conf
Installing Podman Compose
# Install via pip
sudo dnf install -y python3-pip
pip3 install --user podman-compose
# Or install from repository
sudo dnf install -y podman-compose
# Verify installation
podman-compose --version
Basic Podman Commands
Version and System Information
# Show Podman version
podman version
# Display system information
podman info
# Show detailed system info
podman system info
# Display disk usage
podman system df
Help and Documentation
# General help
podman --help
# Command-specific help
podman run --help
# Man pages
man podman
man podman-run
Basic Container Operations
# Run a container
podman run hello-world
# Run interactive container
podman run -it alpine /bin/sh
# Run container in background
podman run -d nginx
# Run with custom name
podman run -d --name webserver nginx
# Run with port mapping
podman run -d -p 8080:80 --name web nginx
Working with Container Images
Searching for Images
# Search for images on registries
podman search nginx
# Search with filters
podman search nginx --filter stars=10
# Search specific registry
podman search quay.io/nginx
# Limit search results
podman search --limit 5 postgresql
Pulling Images
# Pull latest image
podman pull nginx
# Pull specific version
podman pull nginx:1.21
# Pull from specific registry
podman pull quay.io/nginx
# Pull multiple architectures
podman pull --all-tags alpine
# Pull with progress bar suppressed
podman pull -q redis
Listing Images
# List all images
podman images
# List with specific format
podman images --format "table {{.Repository}} {{.Tag}} {{.Size}}"
# List image IDs only
podman images -q
# Filter images
podman images --filter reference=nginx
Building Images
Create a Dockerfile:
# Dockerfile
FROM almalinux:9
RUN dnf update -y && \
dnf install -y httpd && \
dnf clean all
COPY index.html /var/www/html/
EXPOSE 80
CMD ["/usr/sbin/httpd", "-D", "FOREGROUND"]
Build the image:
# Build image
podman build -t myapp:latest .
# Build with no cache
podman build --no-cache -t myapp:latest .
# Build with build arguments
podman build --build-arg VERSION=1.0 -t myapp:1.0 .
# Build from specific Dockerfile
podman build -f Dockerfile.prod -t myapp:prod .
# Multi-stage build
podman build --target production -t myapp:prod .
Managing Images
# Tag an image
podman tag nginx:latest mynginx:v1
# Remove an image
podman rmi nginx
# Remove all unused images
podman image prune
# Remove all images
podman rmi -a
# Save image to file
podman save -o nginx.tar nginx
# Load image from file
podman load -i nginx.tar
# Export image
podman export webserver > webserver.tar
# Import image
podman import webserver.tar mynewimage
Container Management
Running Containers
# Run with environment variables
podman run -e MYSQL_ROOT_PASSWORD=secret -d mysql
# Run with volume mount
podman run -v /host/data:/container/data:Z nginx
# Run with resource limits
podman run --memory 512m --cpus 1 nginx
# Run with restart policy
podman run -d --restart always nginx
# Run in privileged mode
podman run --privileged -d nginx
# Run with custom user
podman run --user 1000:1000 nginx
Container Lifecycle Management
# List running containers
podman ps
# List all containers
podman ps -a
# Stop container
podman stop webserver
# Start container
podman start webserver
# Restart container
podman restart webserver
# Pause container
podman pause webserver
# Unpause container
podman unpause webserver
# Remove container
podman rm webserver
# Remove running container
podman rm -f webserver
Interacting with Containers
# Execute command in running container
podman exec webserver ls -la
# Interactive shell in container
podman exec -it webserver /bin/bash
# Attach to running container
podman attach webserver
# View container logs
podman logs webserver
# Follow container logs
podman logs -f webserver
# View last 50 log lines
podman logs --tail 50 webserver
# Copy files to/from container
podman cp file.txt webserver:/tmp/
podman cp webserver:/var/log/nginx/access.log ./
Container Inspection
# Inspect container
podman inspect webserver
# Get specific information
podman inspect webserver --format '{{.NetworkSettings.IPAddress}}'
# View container processes
podman top webserver
# View container stats
podman stats webserver
# View all containers stats
podman stats --all
# Container diff
podman diff webserver
# Container health check
podman healthcheck run webserver
Networking in Podman
Network Management
# List networks
podman network ls
# Create network
podman network create mynetwork
# Create network with subnet
podman network create --subnet 172.20.0.0/16 customnet
# Inspect network
podman network inspect mynetwork
# Remove network
podman network rm mynetwork
# Connect container to network
podman network connect mynetwork webserver
# Disconnect from network
podman network disconnect mynetwork webserver
Running Containers with Networks
# Run container on specific network
podman run -d --network mynetwork --name web1 nginx
# Run with multiple networks
podman run -d --network net1 --network net2 nginx
# Run with host network
podman run -d --network host nginx
# Run with no network
podman run -d --network none nginx
# Port mapping
podman run -d -p 8080:80 nginx
podman run -d -p 127.0.0.1:8080:80 nginx
podman run -d -p 8080-8090:80-90 nginx
DNS and Hostname Configuration
# Set container hostname
podman run -d --hostname myserver nginx
# Add hosts entry
podman run -d --add-host db:172.20.0.10 nginx
# Set DNS servers
podman run -d --dns 8.8.8.8 --dns 8.8.4.4 nginx
# Set DNS search domains
podman run -d --dns-search example.com nginx
Volume Management
Creating and Managing Volumes
# Create volume
podman volume create mydata
# List volumes
podman volume ls
# Inspect volume
podman volume inspect mydata
# Remove volume
podman volume rm mydata
# Remove all unused volumes
podman volume prune
# Create volume with options
podman volume create --opt device=/dev/sdb1 --opt type=ext4 myvolume
Using Volumes with Containers
# Named volume
podman run -d -v mydata:/data nginx
# Anonymous volume
podman run -d -v /data nginx
# Bind mount
podman run -d -v /host/path:/container/path:Z nginx
# Read-only volume
podman run -d -v mydata:/data:ro nginx
# Multiple volumes
podman run -d \
-v config:/etc/nginx \
-v data:/usr/share/nginx/html \
-v logs:/var/log/nginx \
nginx
Volume Backup and Restore
# Backup volume
podman run --rm \
-v mydata:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/mydata-backup.tar.gz -C /source .
# Restore volume
podman run --rm \
-v mydata:/target \
-v $(pwd):/backup:ro \
alpine tar xzf /backup/mydata-backup.tar.gz -C /target
Podman Compose
Basic docker-compose.yml
version: '3'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:Z
networks:
- webnet
db:
image: postgres:13
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- dbdata:/var/lib/postgresql/data
networks:
- webnet
volumes:
dbdata:
networks:
webnet:
Using Podman Compose
# Start services
podman-compose up -d
# View running services
podman-compose ps
# View logs
podman-compose logs
# Stop services
podman-compose stop
# Remove services
podman-compose down
# Remove with volumes
podman-compose down -v
# Rebuild images
podman-compose build
# Scale services
podman-compose up -d --scale web=3
Rootless Containers
Setting Up Rootless Podman
# Check subuid/subgid allocation
grep $USER /etc/subuid /etc/subgid
# Configure user namespaces
podman unshare cat /proc/self/uid_map
# Test rootless container
podman run --rm hello-world
# Check rootless configuration
podman info --format '{{.Host.Security.Rootless}}'
Rootless Networking
# Check available port range
cat /proc/sys/net/ipv4/ip_unprivileged_port_start
# Run rootless container with port mapping
podman run -d -p 8080:80 nginx
# Use slirp4netns for better performance
podman run -d --network slirp4netns:port_handler=slirp4netns -p 8080:80 nginx
Storage Configuration for Rootless
# Configure storage location
mkdir -p ~/.config/containers
cat > ~/.config/containers/storage.conf << EOF
[storage]
driver = "overlay"
runroot = "$HOME/.local/share/containers/storage"
graphroot = "$HOME/.local/share/containers/storage"
EOF
# Check storage configuration
podman info --format '{{.Store.GraphRoot}}'
Systemd Integration
Generating Systemd Services
# Create container
podman create --name webapp -p 8080:80 nginx
# Generate systemd service
podman generate systemd --name webapp > webapp.service
# Generate with restart policy
podman generate systemd --restart-policy always --name webapp
# Generate for user service
podman generate systemd --new --name webapp > ~/.config/systemd/user/webapp.service
# Enable and start service
systemctl --user daemon-reload
systemctl --user enable webapp.service
systemctl --user start webapp.service
Auto-starting Containers at Boot
# Enable lingering for user
sudo loginctl enable-linger $USER
# Create container with systemd
podman run -d --name myapp --systemd=true nginx
# Generate and install service
cd ~/.config/systemd/user
podman generate systemd --new --name myapp > container-myapp.service
systemctl --user enable container-myapp.service
Managing Podman with Systemd
# View service status
systemctl --user status container-myapp.service
# View logs
journalctl --user -u container-myapp.service
# Restart service
systemctl --user restart container-myapp.service
# Stop service
systemctl --user stop container-myapp.service
Migration from Docker
Docker Compatibility
# Enable Docker compatibility
sudo dnf install -y podman-docker
# Create Docker command alias
alias docker=podman
# Test Docker commands
docker run hello-world
docker ps
docker images
Converting Docker Commands
# Docker command
docker run -d -p 80:80 -v /data:/var/www/html nginx
# Equivalent Podman command
podman run -d -p 80:80 -v /data:/var/www/html:Z nginx
# Docker Compose
docker-compose up -d
# Podman Compose
podman-compose up -d
Migrating Images
# Export from Docker
docker save nginx > nginx.tar
# Import to Podman
podman load < nginx.tar
# Or use skopeo
skopeo copy docker-daemon:nginx:latest containers-storage:nginx:latest
Key Differences to Consider
- SELinux Labels: Add
:Z
or:z
to volume mounts - User Namespaces: Rootless containers use different UIDs
- Networking: Different network stack implementation
- Systemd Integration: Better in Podman
- Pod Support: Native in Podman
Security Features
SELinux Integration
# Run with SELinux context
podman run -v /data:/data:Z nginx
# Check SELinux context
ls -lZ /data
# Run with custom SELinux type
podman run --security-opt label=type:container_file_t nginx
# Disable SELinux for container
podman run --security-opt label=disable nginx
Seccomp Profiles
# Run with default seccomp profile
podman run --security-opt seccomp=/usr/share/containers/seccomp.json nginx
# Run without seccomp
podman run --security-opt seccomp=unconfined nginx
# Custom seccomp profile
podman run --security-opt seccomp=./custom-seccomp.json nginx
User Namespace Mapping
# View namespace mappings
podman unshare cat /proc/self/uid_map
# Run with specific user mapping
podman run --uidmap 0:100000:5000 nginx
# Run with keep-id
podman run --userns=keep-id nginx
Capabilities Management
# Drop all capabilities
podman run --cap-drop=all nginx
# Add specific capability
podman run --cap-add=NET_ADMIN nginx
# List capabilities
podman run --cap-add=all --security-opt seccomp=unconfined alpine capsh --print
Advanced Features
Working with Pods
# Create pod
podman pod create --name mypod -p 8080:80
# Add container to pod
podman run -d --pod mypod nginx
# List pods
podman pod ls
# Inspect pod
podman pod inspect mypod
# Stop pod
podman pod stop mypod
# Remove pod
podman pod rm mypod
# Generate Kubernetes YAML
podman generate kube mypod > mypod.yaml
Container Checkpointing
# Checkpoint running container
podman container checkpoint myapp
# List checkpointed containers
podman container list --all
# Restore container
podman container restore myapp
# Checkpoint with export
podman container checkpoint myapp --export=/tmp/checkpoint.tar.gz
# Restore from export
podman container restore --import=/tmp/checkpoint.tar.gz
Building with Buildah
# Create working container
buildah from almalinux:9
# Run commands
buildah run almalinux-working-container dnf install -y httpd
# Copy files
buildah copy almalinux-working-container index.html /var/www/html/
# Configure
buildah config --port 80 almalinux-working-container
# Commit image
buildah commit almalinux-working-container mywebserver
Registry Operations with Skopeo
# Inspect remote image
skopeo inspect docker://docker.io/nginx:latest
# Copy between registries
skopeo copy docker://nginx:latest docker://myregistry.com/nginx:latest
# Delete image from registry
skopeo delete docker://myregistry.com/nginx:latest
# List tags
skopeo list-tags docker://docker.io/nginx
Troubleshooting
Common Issues and Solutions
1. Permission Denied Errors
# Check user namespaces
sysctl user.max_user_namespaces
# Fix subuid/subgid
sudo usermod --add-subuids 100000-165535 $USER
sudo usermod --add-subgids 100000-165535 $USER
# Reset Podman
podman system reset
2. Network Issues
# Check network plugins
ls /usr/libexec/cni/
# Reinstall plugins
sudo dnf reinstall containernetworking-plugins
# Check firewall
sudo firewall-cmd --list-all
3. Storage Issues
# Clean up storage
podman system prune -a
# Check storage driver
podman info --format '{{.Store.GraphDriverName}}'
# Reset storage
rm -rf ~/.local/share/containers/storage
4. SELinux Issues
# Check SELinux denials
sudo ausearch -m avc -ts recent
# Generate policy
sudo audit2allow -M mypolicy < /tmp/audit.log
sudo semodule -i mypolicy.pp
Debugging Containers
# Verbose output
podman --log-level debug run nginx
# Check events
podman events
# System information
podman system info
# Check container logs
podman logs --timestamps --follow container_name
# Debug networking
podman run --rm --network container:myapp nicolaka/netshoot ss -tulpn
Performance Monitoring
# Monitor resource usage
podman stats
# Check cgroup limits
podman exec myapp cat /sys/fs/cgroup/memory/memory.limit_in_bytes
# Monitor I/O
podman exec myapp iostat -x 1
# Check process tree
podman top myapp
Best Practices
Image Management
- Use specific tags: Avoid using
latest
in production - Minimize layers: Combine RUN commands
- Multi-stage builds: Reduce final image size
- Regular updates: Keep base images updated
- Scan for vulnerabilities: Use
podman scan
Container Security
- Run rootless: Use rootless containers when possible
- Drop capabilities: Remove unnecessary capabilities
- Use SELinux: Keep SELinux enabled
- Non-root user: Run processes as non-root inside containers
- Read-only filesystem: Use
--read-only
when possible
Resource Management
- Set limits: Always set memory and CPU limits
- Health checks: Implement container health checks
- Logging: Configure appropriate log drivers
- Monitoring: Implement proper monitoring
- Cleanup: Regular cleanup of unused resources
Conclusion
Podman provides a secure, daemonless alternative to Docker with excellent compatibility and additional features like native pod support and systemd integration. Its rootless capabilities and SELinux integration make it particularly suitable for security-conscious environments.
Key takeaways:
- Podman is a drop-in replacement for Docker
- Rootless containers enhance security
- Native systemd integration simplifies management
- Pod support enables Kubernetes-style deployments
- Strong security features with SELinux and seccomp
Whether you’re migrating from Docker or starting fresh with containers, Podman on AlmaLinux provides a robust, secure, and efficient container platform for modern applications.
Additional Resources
- Podman Documentation
- Red Hat Container Tools
- Podman GitHub Repository
- Container Security Guide
- Man pages: podman(1), podman-run(1), podman-build(1)