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.
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.