Podman has quietly become the default container engine on every major enterprise Linux distribution. Red Hat, SUSE, and Oracle ship it out of the box. Kubernetes moved away from Docker's runtime years ago. And yet, most developers still reach for docker out of habit — whether they're running microservices or deploying analytics tools like Metabase with Docker and DeployHQ.
If you're deploying containers — especially in production — Podman deserves a serious look. Not because it's Docker but open source
(Docker is also open source), but because its architecture solves real operational problems that Docker's design cannot.
What Podman actually is
Podman (Pod Manager) is a container engine developed by Red Hat that creates, runs, and manages OCI-compatible containers. It's been part of RHEL since version 8, replacing Docker as the default container tool.
The important distinction: Podman isn't a Docker wrapper or compatibility layer. It's a ground-up implementation that happens to support the same container image format and (mostly) the same CLI interface. Under the hood, it works fundamentally differently.
The architectural difference that matters
Docker runs a persistent daemon (dockerd) as root. Every container operation — start, stop, build, pull — goes through this single process:
flowchart LR
A[docker CLI] -->|API call| B[dockerd daemon]
B -->|spawns| C[containerd]
C -->|manages| D[container 1]
C -->|manages| E[container 2]
C -->|manages| F[container N]
Podman has no daemon. Each container runs as a direct child process of the command that started it:
flowchart LR
A[podman run] -->|fork/exec| B[conmon]
B -->|manages| C[container]
D[podman run] -->|fork/exec| E[conmon]
E -->|manages| F[container]
This isn't a minor implementation detail. It changes how containers behave in production:
- No single point of failure. If Docker's daemon crashes, every container on the host dies. With Podman, containers are independent processes — one crashing doesn't affect others.
- Containers survive restarts. Because Podman containers aren't children of a daemon, they persist through Podman updates and restarts. Docker containers die when
dockerdrestarts. - Lower idle resource usage. Docker's daemon consumes 140-180 MB of memory just sitting there. Podman uses 60-70% less memory at idle because there's nothing running between operations.
- Better scaling. Benchmarks show Docker starts to degrade with 100+ containers because every operation funnels through the daemon. Podman maintains linear performance because each container is an independent process.
The trade-off: Docker's daemon gives it a ~10-15% edge in individual operation speed (container start takes ~150ms vs ~180ms for Podman) because the daemon keeps connections warm. For most workloads, you won't notice this. For development inner loops where you're restarting containers constantly, it's worth knowing.
Rootless containers: security without the overhead
Docker can run rootless (since Docker 20.10), but it was bolted on after the fact. Podman was designed rootless from day one, and it shows.
Running rootless means:
# No sudo needed — runs entirely as your user
podman run -d -p 8080:80 nginx
Podman maps container UIDs to unprivileged ranges in your user namespace. Even if an attacker escapes the container, they land as an unprivileged user with no access to the host system.
This matters operationally because:
- Shared CI runners become safer. Multiple teams can run container builds on the same machine without root escalation risks.
- Compliance becomes easier. Many security frameworks (PCI-DSS, SOC2) require justification for any root-level process. Rootless Podman eliminates that conversation entirely.
- Developer machines are protected. A malicious container image can't compromise the host when running rootless.
Pods: the feature Docker doesn't have
Podman's namesake feature — pods — lets you group containers that share a network namespace, just like Kubernetes pods:
# Create a pod with a shared port
podman pod create --name webapp -p 8080:80
# Add containers to the pod — they share localhost
podman run -d --pod webapp --name web nginx
podman run -d --pod webapp --name cache redis
podman run -d --pod webapp --name api node:20-slim
# Containers communicate via localhost
# The API container can reach Redis at localhost:6379
This isn't just syntactic sugar. It means you can develop with the same networking model you'll use in Kubernetes production, without running a local cluster. Your localhost references in application code work identically in development and in a Kubernetes pod.
You can even export a pod definition as a Kubernetes YAML manifest:
podman generate kube webapp > webapp.yaml
This generates a valid Kubernetes Pod spec that you can apply directly to a cluster. No rewriting Docker Compose files into Kubernetes manifests.
Quadlet: containers as systemd services
This is where Podman pulls decisively ahead of Docker for production Linux deployments. Quadlet lets you define containers as systemd unit files — the same system that manages every other service on your Linux server.
Create a file at ~/.config/containers/systemd/webapp.container:
[Container]
Image=docker.io/library/nginx:stable
PublishPort=8080:80
Volume=webapp-data.volume:/usr/share/nginx/html:ro
[Service]
Restart=always
[Install]
WantedBy=default.target
Then activate it:
systemctl --user daemon-reload
systemctl --user start webapp
systemctl --user enable webapp # starts on boot
Now your container is managed exactly like any other systemd service. It gets automatic restarts, dependency ordering, journal logging, and resource limits — all through the same tooling your operations team already knows. No need for Docker Compose, no need for a separate orchestration layer for single-host deployments.
Quadlet supports .container, .pod, .volume, .network, and .image unit types. For multi-container applications on a single host, this is simpler and more reliable than Docker Compose because systemd handles the lifecycle management natively.
Podman Desktop: the GUI option
If you're coming from Docker Desktop, Podman Desktop is the equivalent — a GUI for managing containers, images, pods, and Kubernetes clusters. It crossed 3 million downloads in 2025 and was contributed to the Cloud Native Computing Foundation (CNCF) as a sandbox project.
It runs on macOS, Windows, and Linux, and includes:
- Container and pod management with log streaming
- Image building and registry management
- Kubernetes cluster integration
- Extension ecosystem (similar to Docker Desktop extensions)
On macOS and Windows, Podman Desktop manages the Linux VM that runs containers (since containers are a Linux kernel feature). Podman 5.0 brought native Apple Hypervisor support, making the macOS experience significantly faster than the previous QEMU-based approach.
Migrating from Docker: what actually works and what doesn't
The common advice is just alias `docker` to `podman`.
That's partially true, but skipping the nuances will cost you time.
What works seamlessly:
# These are identical in both tools
podman pull nginx
podman build -t myapp .
podman run -d -p 8080:80 myapp
podman ps
podman logs <container>
podman exec -it <container> bash
The podman-docker package even creates a docker binary that calls podman, so existing scripts work without modification:
# On Fedora/RHEL
sudo dnf install podman-docker
# Now 'docker' commands route to podman
What needs attention:
- Docker Compose. Podman ships
podman compose(note: no hyphen) since version 4.7, which delegates to an external compose provider. It supports most Docker Compose features but has edge cases with networking and volume mounts. Test yourdocker-compose.ymlfiles — don't assume they'll work identically. - Volume mount permissions. Rootless Podman maps UIDs differently. If your Docker setup assumes root inside the container can write to bind mounts, you'll need to add
:Zor:zSELinux labels, or usepodman unshareto fix ownership. - Docker socket. Tools that talk to
/var/run/docker.sockneed to be pointed at Podman's socket instead:podman system service --time=0 unix:///tmp/podman.sock. Or usepodman machineon macOS which exposes a Docker-compatible socket automatically. - Networking in rootless mode. Rootless containers can't bind to ports below 1024 without
sysctladjustments. Port 80 inside a rootless container needs to be mapped to a higher port on the host:-p 8080:80.
Podman in CI/CD pipelines
Podman's rootless, daemonless architecture makes it ideal for CI/CD where you're building and pushing container images. No privileged daemon means no Docker-in-Docker hacks.
GitHub Actions example:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build container image
run: podman build -t myapp:${{ github.sha }} .
- name: Push to registry
run: |
podman login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
podman push myapp:${{ github.sha }} ghcr.io/${{ github.repository }}/myapp:${{ github.sha }}
GitLab CI example:
build:
image: quay.io/podman/stable
script:
- podman build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- podman login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- podman push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
No --privileged flag. No DinD service. No security trade-offs.
Deploying containerized applications with DeployHQ
If you're using DeployHQ to manage your deployments, containerized workflows fit naturally into the platform. DeployHQ can trigger deployments from your repository — when you push changes, DeployHQ handles getting your code to your servers.
For container-based workflows, this typically looks like:
- Push code to your Git repository
- DeployHQ detects the change and deploys updated files to your server
- Build hooks run your container build and restart commands on the server
Using DeployHQ's build pipeline features, you can run Podman build commands as part of your deployment:
# In your DeployHQ build commands
podman build -t myapp:latest .
podman stop myapp || true
podman rm myapp || true
podman run -d --name myapp -p 8080:80 myapp:latest
For teams managing microservices architectures, Podman's pod support means you can group related services and manage them as a unit — matching your Kubernetes production setup.
If you're running containers on a VPS or dedicated server, check out our guide on Docker container deployment with DeployHQ — the same patterns apply to Podman since the CLI is compatible.
When Podman is the right choice
Choose Podman when:
- You're running containers on Linux servers in production (Quadlet + systemd is a genuine advantage)
- Security compliance requires rootless operation without exceptions
- You're building container images in CI/CD and want to avoid privileged Docker daemons
- You're developing applications destined for Kubernetes (pods give you a head start)
- You're on RHEL, CentOS Stream, or Fedora (it's already installed)
Stick with Docker when:
- Your team's muscle memory and existing tooling is Docker-native and switching cost is high
- You rely heavily on Docker Desktop's ecosystem of extensions
- You're running Docker Compose setups with complex networking that haven't been tested on Podman
- You need maximum single-container startup speed for development inner loops
The honest truth: for many development workflows, Docker and Podman are interchangeable. The differences matter most in production, CI/CD, and security-sensitive environments. Pick one, learn it well, and know that switching later is straightforward.
Getting started
On Fedora/RHEL/CentOS:
sudo dnf install podman
On Ubuntu/Debian:
sudo apt-get update && sudo apt-get install -y podman
On macOS:
brew install podman
podman machine init
podman machine start
Verify the installation:
podman info --format '{{.Version.Version}}'
podman run hello-world
If you're migrating from Docker, install the compatibility package and test your existing workflows:
sudo dnf install podman-docker # Fedora/RHEL
# Or on Ubuntu/Debian:
sudo apt-get install podman-docker
Ready to streamline your container deployments? DeployHQ automates deployment workflows for teams of all sizes — whether you're using Docker, Podman, or deploying directly from Git. Start your free trial.
For questions or feedback, reach out at support@deployhq.com or find us on Twitter/X.