
September 09, 2026
14 min read
By Kokil Thapa | Last reviewed: September 2026
Podman: A Daemonless Docker Alternative solves a problem Docker created on every Linux server I maintain: one long-running daemon with root privileges, a Unix socket, and a single point of failure. If that daemon dies or gets compromised, every container on the host is at risk. Podman runs each container as an ordinary process forked from your shell or systemd unit. There is no central broker. For teams running Linux system administration on Ubuntu EC2 boxes alongside Laravel apps, that architecture change matters more than a CLI rename.
What makes Podman a daemonless Docker alternative?
Docker's model depends on dockerd, a persistent root-owned daemon. Your CLI talks to it over /var/run/docker.sock. Every docker run is really a remote procedure call. That design is convenient, but it concentrates privilege.
Podman inverts the model. When you run podman run nginx, Podman forks, execs conmon (the container monitor), and starts the OCI runtime (crun or runc). The container becomes a child process tree under your user or systemd—not under a shared daemon. Kill Podman and you kill one container, not the entire runtime.
Both tools consume the same OCI image format. A image you build with Docker or multi-stage Docker builds runs unchanged in Podman. The difference is operational security and process ownership, not container contents.
Core components you should know
- Podman — runs and manages containers and pods.
- Buildah — builds OCI images;
podman buildwraps it. - skopeo — copies and inspects images across registries without a daemon.
- conmon — monitors container I/O and exit codes.
- Netavark — modern networking stack replacing legacy CNI plugins in recent Podman releases.
On Fedora and RHEL-family systems, Podman is the default container engine. On Ubuntu servers where I deploy Laravel with GitLab CI, Podman is an opt-in replacement that fits existing Docker-on-Ubuntu knowledge without retraining the whole team.
| Criteria | Docker Engine | Podman |
|---|---|---|
| Architecture | Central dockerd daemon | Daemonless fork/exec per container |
| Rootless default | Supported but secondary | First-class; recommended path |
| systemd integration | Requires manual unit files | Native; Quadlet and podman generate systemd |
| Kubernetes pods | Not native | Native podman pod concept |
| Socket attack surface | docker.sock grants root-equivalent access | No daemon socket in default mode |
| Compose support | Built-in docker compose | podman-compose or Docker Compose with Podman socket |
| macOS/Windows dev | Docker Desktop VM | podman machine lightweight VM |
How do you install Podman on Ubuntu for production use?
Ubuntu 24.04 ships Podman in the default repositories. Ubuntu 22.04 may need the Kubic stable repo for a current version. I prefer the distro package on 24.04 and the Kubic repo on older LTS boxes still running PHP-FPM workloads.
Install on Ubuntu 24.04
sudo apt update
sudo apt install -y podman podman-compose
podman --version
podman info --format '{{.Host.Security.Rootless}}' Install on Ubuntu 22.04 via Kubic repo
sudo apt install -y curl gnupg2
source /etc/os-release
echo "deb https://download.opensuse.org/reports/deb/xUbuntu_${VERSION_ID}/ /" \
| sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -fsSL https://download.opensuse.org/reports/deb/xUbuntu_${VERSION_ID}/Release.key \
| sudo gpg --dearmor -o /etc/apt/keyrings/libcontainers-archive-keyring.gpg
sudo apt update
sudo apt install -y podman Verify rootless prerequisites before you run anything in production. Podman needs user namespaces enabled. On most Ubuntu kernels they are on by default. Check with:
cat /proc/sys/kernel/unprivileged_userns_clone
sysctl kernel.unprivileged_userns_clone A value of 1 means rootless Podman will work. If it reads 0, rootless mode fails with obscure permission errors. Fix it in /etc/sysctl.d/99-rootless.conf and reload.
Enable Docker CLI compatibility
The podman-docker package installs a docker shim that forwards to Podman. Useful for legacy scripts and CI jobs that call docker blindly.
sudo apt install -y podman-docker
docker --version
docker ps Do not assume every Docker flag maps 1:1. Swarm commands, certain buildx features, and legacy links syntax differ. Test your critical paths on a staging host first. Our Podman vs Docker migration guide covers the common breakages.
How does rootless Podman work and what breaks?
Rootless mode is the main reason teams adopt Podman on shared servers. A compromised app container cannot easily pivot to full root through a daemon socket—because there is no daemon socket.
When user deploy runs a container rootlessly, Podman maps UIDs inside the container to a range defined in /etc/subuid and /etc/subgid. Root inside the container (UID 0) becomes UID 100999 (or similar) on the host. Files written to bind mounts carry that mapped ownership.
Configure subuid and subgid for deploy users
sudo usermod --add-subuids 100000-165535 deploy
sudo usermod --add-subgids 100000-165535 deploy
grep deploy /etc/subuid /etc/subgid
loginctl enable-linger deploy The enable-linger step matters. Without it, user systemd units stop when the SSH session closes. Production containers managed by systemd user services will die on logout.
Fix the Laravel storage permission trap
On a production Laravel application, I bind-mount storage/ and bootstrap/cache/. Rootless Podman writes those as UID 100999. Host PHP-FPM running as www-data cannot write logs. Three fixes work in practice:
- Run the container with
--userns=keep-idso container UID matches host UID. - Pre-create directories with
chown 100999:100999 storage -Ron the host. - Use a named volume instead of a bind mount for writable paths.
I hit this on sister sites sharing a Deployer 7 pipeline. The app worked in rootful Docker locally but failed silently in rootless Podman after deploy. Always test write paths, not just HTTP 200 responses.
Ports below 1024 in rootless mode
Rootless containers cannot bind host ports 1–1024 without extra setup. Use sysctl net.ipv4.ip_unprivileged_port_start=80 or put Nginx on the host as reverse proxy to a high port. On legal-tech portals I often run Apache on the host and keep app containers on 8080+ anyway—same pattern as Court Marriage In Nepal infrastructure.
How do you migrate existing Docker workflows to Podman?
Migration is rarely a big-bang cutover. I run a phased approach on EC2 hosts that already serve PHP-FPM and MySQL outside containers.
Step 1: Export your running state
docker ps -a --format '{{.Names}}' > /tmp/docker-containers.txt
docker images --format '{{.Repository}}:{{.Tag}}' > /tmp/docker-images.txt
docker volume ls -q > /tmp/docker-volumes.txt Step 2: Pull the same images with Podman
podman pull redis:8-alpine
podman pull postgres:18-alpine
podman pull nginx:alpine Images from Docker Hub, GitLab Container Registry, or a self-hosted Docker registry pull identically. Authentication uses the same ~/.docker/config.json or podman login.
Step 3: Convert run commands
Most one-liners translate directly:
docker run -d --name redis -p 6379:6379 redis:8-alpine
podman run -d --name redis -p 6379:6379 redis:8-alpine For PostgreSQL dev databases, the same pattern from our PostgreSQL in Docker guide works with podman run. Add --restart=always or prefer systemd for production restarts.
Step 4: Generate systemd units
podman generate systemd --name redis --files --new
mkdir -p ~/.config/systemd/user/
mv container-redis.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now container-redis.service On modern Podman, Quadlet is cleaner. Drop a .container file in ~/.config/containers/systemd/:
[Container]
Image=docker.io/library/redis:8-alpine
PublishPort=6379:6379
AutoUpdate=registry
[Service]
Restart=always Run systemctl --user daemon-reload. systemd generates and manages the unit. This beats hand-written ExecStart lines that go stale after image tag changes.
Edge cases that still bite teams
- Docker Swarm and Compose profiles — not supported natively. Move orchestration to systemd, Nomad, or Kubernetes vs Docker Swarm decision paths.
- GPU passthrough — requires rootful Podman or specific device cgroup rules.
- Host networking — rootless host network behaves differently; test before assuming
--network hostparity. - inotify on macOS — use
podman machinewith virtiofs; bind mounts can be slow. - Health checks in old Compose files — verify
HEALTHCHECKin Dockerfile or Composehealthcheck:blocks; Podman respects OCI health checks.
Can you run Docker Compose and Laravel Sail with Podman?
Yes, with caveats. Three paths exist in 2026.
Option A: podman-compose (Python)
pip install podman-compose
podman-compose -f docker-compose.yml up -d Works for simple multi-container dev stacks. Some Compose v3 features lag behind Docker Compose v2. Test volume paths and network aliases.
Option B: Docker Compose with Podman socket
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
docker compose up -d This preserves the exact Compose CLI your team knows. The socket exposes a Docker-compatible API backed by Podman. Official Podman docs describe this path for teams migrating CI pipelines.
Option C: Laravel Sail adjustments
Laravel Sail assumes Docker Desktop or dockerd. For local Laravel dev, I still recommend Sail on Docker for the smoothest path—see local Laravel dev with Sail and the Sail vs Docker Compose comparison.
If you must use Podman, set DOCKER_HOST to the Podman socket and install podman-docker. Watch for volume speed on bind-mounted vendor/ directories. On Linux bare metal, performance is usually fine. On podman machine on macOS, run composer install inside the container, not on the mounted host path.
For production Laravel on EC2, I rarely containerize the PHP app itself. I containerize Redis, Meilisearch, or queue workers. Podman fits that sidecar model well alongside Apache and PHP-FPM on the host—a pattern we use on Adventure Third Pole Trek infrastructure.
How do you harden and operate Podman in production?
Daemonless does not mean zero maintenance. You still manage images, logs, updates, and resource limits.
Resource limits
Same flags as Docker—see our guide on limiting Docker container resources:
podman run -d \
--name queue-worker \
--memory=512m \
--cpus=1.0 \
--pids-limit=100 \
my-registry/queue-worker:latest Logging and debugging
podman logs -f queue-worker
podman inspect queue-worker --format '{{.State.Status}}'
podman stats Parse JSON logs with our JSON formatter tool when apps emit structured logging. Ship logs to journald by default when systemd manages the unit.
Automatic image updates
podman auto-update --dry-run
podman auto-update Label containers or Quadlet units with AutoUpdate=registry. Podman pulls new digests on a timer. Pair with health checks before you trust auto-updates on payment webhook workers.
Networking with Netavark and pasta
Recent Podman releases use Netavark as the default network backend. Rootless containers get IP via slirp4netns or pasta. For service discovery between containers, use Compose networks or Podman pods:
podman pod create --name app-stack -p 8080:80
podman run -d --pod app-stack --name web nginx:alpine
podman run -d --pod app-stack --name api myapp:latest Containers in a pod share a network namespace—similar to Kubernetes. Useful when you front an API with Nginx and want localhost communication without overlay DNS.
For reverse proxy integration, Traefik or host Nginx still terminate TLS. See Traefik as reverse proxy for containers and Docker networking and volumes—concepts transfer directly.
Security practices that matter
- Run rootless unless you have a concrete reason not to.
- Never expose
podman.socketto untrusted networks—it recreates Docker's socket risk. - Use read-only root filesystem where possible:
--read-onlywith tmpfs mounts for/tmp. - Drop capabilities:
--cap-drop=ALLand add only what you need. - Scan images with
podman scanor your registry's scanner before deploy.
The official Podman documentation at docs.podman.io and the upstream project at github.com/containers/podman are the authoritative references for flag changes between releases. Red Hat's rootless guide covers edge cases for enterprise SELinux hosts; Ubuntu uses AppArmor instead, but UID mapping rules are identical.
When should you choose Podman over Docker in 2026?
Choose Podman when security isolation and systemd-native operations matter more than Docker Desktop convenience. Strong fits include:
- Shared Linux servers where multiple developers SSH in and run containers.
- CI runners that should not grant jobs root-equivalent socket access.
- Fedora/RHEL/CentOS Stream environments where Podman is preconfigured.
- Teams planning a Kubernetes migration who want pod semantics locally.
- Regulated workloads that audit process trees and reject background daemons.
Stick with Docker when your team depends on Docker Desktop on macOS/Windows, Swarm orchestration, or deep buildx multi-platform features you have not validated on Podman. Our Docker Buildx multi-platform guide and Compose multi-container setup remain the fastest path for pure Docker shops.
On budget-sensitive Nepal hosting (Rs 2,500–5,000/month VPS, ~USD 19–37), a single Ubuntu VPS running rootless Podman sidecars plus host PHP often beats paying for managed container platforms. You keep control without Kubernetes overhead.
For ongoing ops after migration, support and maintenance covers the systemd units, backups, and upgrade paths that outlive the initial install. If you are containerizing a new enterprise application, decide Podman vs Docker during architecture review—not after the first production incident.
Key Takeaways
- Podman runs OCI containers without dockerd; each container is an independent process tree managed by conmon and crun/runc.
- Rootless mode removes the docker.sock attack surface but requires subuid/subgid setup and careful bind-mount ownership for Laravel and PHP apps.
- Migration is phased: install Podman alongside Docker, validate on staging, generate systemd or Quadlet units, then disable dockerd.
- Docker Compose works via podman-compose or DOCKER_HOST pointing at podman.socket; Laravel Sail still prefers native Docker on dev machines.
- Production hardening means resource limits, auto-update labels, health checks, and keeping the Podman socket off public interfaces.
- Choose Podman for Linux server security and systemd integration; keep Docker where Desktop, Swarm, or untested buildx workflows dominate.
People Also Ask
Is Podman fully compatible with Docker commands?
Most daily commands—run, ps, build, pull, exec, logs—are compatible, especially with the podman-docker shim. Swarm, some legacy network flags, and certain buildx features differ. Always test your CI scripts on a staging host before cutover.
Does Podman work on macOS and Windows?
Yes, through podman machine, which starts a lightweight Linux VM similar to Docker Desktop's backend. Install via Homebrew on macOS or the Windows installer. Performance on bind mounts can lag native Linux; prefer named volumes or run package managers inside the container.
Can Podman replace Docker in Kubernetes?
Podman is not a Kubernetes replacement. It complements Kubernetes by running local pod-like groups and generating systemd units on single nodes. Kubernetes still orchestrates clusters; Podman is the node-level runtime alternative to containerd paired with dockerd on bare VMs.
Is rootless Podman slower than Docker?
Startup overhead is slightly higher due to user namespace setup, but runtime performance is comparable for typical web workloads. Network throughput on rootless slirp4netns can lag host networking; use pasta or host-published ports for latency-sensitive services. CPU and memory limits behave like Docker's cgroup v2 controls.
Run containers without the daemon tax
Podman: A Daemonless Docker Alternative earns its place on production Linux hosts where a root-owned dockerd socket is the weakest link. You keep OCI images, Compose files, and most CLI muscle memory. You gain rootless defaults, systemd-native lifecycle management, and a smaller attack surface. Start with sidecar services—Redis, workers, search—on a staging box, fix volume permissions before you touch Laravel storage, and cut over when metrics stay clean for 48 hours.
If you want help auditing a Docker-based server or planning a Podman migration on Ubuntu, contact us for a practical review. For related reading, see the full migration checklist, container registry comparison, and about the author.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

