Introduction
Podman has become the leading daemonless alternative to Docker, especially suited for secure and rootless environments. In 2026, its ability to generate Kubernetes manifests and integrate natively with systemd through quadlets makes it essential for DevOps architects. This tutorial walks you through building a complete production stack: advanced rootless configuration, multi-container pod management, persistent volumes, and automated deployment. You'll learn to avoid common pitfalls while optimizing security and performance.
Prerequisites
- Podman 5.2+ and podman-compose installed
- Linux system with user namespaces support enabled
- Advanced knowledge of systemd and Linux networking
- Sudo access for initial configuration
Advanced Rootless Configuration
#!/bin/bash
sudo usermod --add-subuids 100000-165535 $(whoami)
sudo usermod --add-subgids 100000-165535 $(whoami)
echo "max_user_namespaces=65536" | sudo tee /etc/sysctl.d/99-podman.conf
sudo sysctl --system
podman system migrateThis script enables user namespaces for a complete rootless environment. The Podman migration updates existing UID/GID mappings.
Creating a Quadlet systemd Unit
[Unit]
Description=MyApp Production Container
After=network-online.target
[Container]
Image=registry.example.com/myapp:2026.1
PublishPort=8080:8080
Volume=myapp-data:/data
Environment=ENV=production
HealthCmd=curl -f http://localhost:8080/health || exit 1
HealthInterval=30s
[Service]
Restart=always
[Install]
WantedBy=multi-user.targetThe quadlet defines a native systemd service managed by Podman. It includes health checks and named volumes for reliable production management.
Deploying the Quadlet
mkdir -p ~/.config/containers/systemd
cp myapp.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start myapp.service
systemctl --user enable myapp.service
podman ps --filter name=myappCopy the quadlet to the user systemd directory, reload, and start. Podman automatically manages the container as a systemd service.
Creating a Multi-Container Pod
podman pod create --name prod-pod --publish 8443:8443 --network podman \
-v prod-data:/data:Z
podman run -d --pod prod-pod --name api \
-e DB_HOST=localhost registry.example.com/api:2026
podman run -d --pod prod-pod --name db \
-v prod-data:/var/lib/postgresql/data:Z postgres:16A pod groups multiple containers sharing network and IPC. The :Z option ensures correct SELinux contexts for shared volumes.
Generating Kubernetes Manifests
podman generate kube prod-pod > prod-pod.yaml
podman kube play prod-pod.yaml --replace
kubectl apply -f prod-pod.yaml --dry-run=client -o yamlGenerate a valid Kubernetes manifest directly from the Podman pod. Test with kubectl before deploying to a real cluster.
Best Practices
- Always use quadlets for managing services in production
- Configure health checks and resource limits (CPU/memory)
- Use named volumes with appropriate SELinux labels
- Always generate Kubernetes manifests for portability
- Monitor logs via journalctl --user -u service-name
Common Mistakes to Avoid
- Forgetting to enable user namespaces before rootless migration
- Running containers without the :Z option on shared volumes
- Neglecting health checks in quadlets
- Using images without digests for critical deployments
Going Further
Deepen your skills with our Learni container and Kubernetes courses. Also explore the official Podman documentation for the latest 2026 features.