Podman vs Docker: Which Container Tool in 2026-2027?
Podman vs Docker 2026: security, rootless design, pricing and licensing, performance, and AI support. Pick the right container engine for your stack today.

Podman vs Docker is the container decision most self-hosters face in 2026. Both run OCI images, but they differ in architecture, security, and now cost. Podman 6 (June 2026) dropped legacy networking stacks and made rootless the only path. Docker Engine 29 (November 2025) made the containerd image store the default for fresh installs. This guide looks at what changed, what it means for your servers, and when to pick each.
What Are Containers?
Containers package your app with everything it needs: code, runtime, libraries, config. It all travels together and runs the same wherever you deploy it.
Why Use Containers?
- Consistent: Same behavior on your laptop and production
- Fast: Start in seconds
- Lightweight: Share the host OS, no full VM needed
- Isolated: Apps don’t step on each other
How They Work
Containers use the host OS kernel but keep everything else separate. You get isolation without the overhead of running a full operating system for each app.
Containers vs VMs
- VMs: Full OS per instance, heavy, slow to boot
- Containers: Shared OS, lightweight, fast startup
Podman vs Docker in 2026: What Changed
State of the Tools (Aug 2026)
Podman 6.0 (June 24, 2026): major release. BoltDB dropped (SQLite only), slirp4netns removed (pasta default), CNI removed (Netavark only), cgroups v1 removed, iptables removed, Intel Mac and Windows 10 support dropped. Podman is now a CNCF Sandbox project. Latest: 6.1.0 (Aug 2026).
Docker Engine 29 (Nov 10, 2025): containerd image store is the default for fresh installs, experimental nftables backend, cgroup v1 deprecated, Docker Content Trust removed from CLI. Latest patch: 29.7.2 (Aug 5, 2026). Docker Desktop ~4.86.
Key shift: Both tools are converging on cgroups v2, nftables, and rootless networking. The gap between them is narrower than ever, but the licensing and security models still diverge.
Both tools are actively maintained and ship regular releases. The biggest changes since mid-2025:
- Podman’s CNCF governance: Red Hat donated Podman Container Tools and Podman Desktop to the CNCF Sandbox in January 2025 (announced at KubeCon NA 2024). The GitHub org is now
podman-container-tools. This matters for long-term neutrality. Podman is no longer just a Red Hat project. The repo has ~32.7k stars on GitHub. - Docker’s containerd image store: Engine 29 made this the default on fresh installs. It uses containerd’s snapshot model instead of the legacy graph driver. Upgraded installs keep the legacy driver unless you opt in. The tradeoff: better compatibility with containerd-based ecosystems, but potentially more disk usage than overlay2 for identical image sets. Moby (the upstream project) has ~72k GitHub stars.
- Rootless networking matured: Podman dropped slirp4netns entirely in 6.0 (pasta is the default, delivering ~8-10 Gbps vs slirp4netns’s ~570 Mbps). Docker Engine 29.5.0 made gvisor-tap-vsock the default rootless network driver. The old “rootless is slow” tax is mostly gone.
- cgroups v1 on the way out: Podman 6 removed cgroups v1 support entirely. Docker Engine 29 deprecated it (support until at least May 2029). If you’re still running cgroups v1, it’s time to plan the migration.
- Docker Content Trust removed from CLI: Engine 29 dropped the
content-trustflags from the CLI. Image signing is now handled through other mechanisms (BuildKit attestations).
Docker vs Podman: Architecture Differences
This is the fundamental difference between the two tools.
Docker: Client-Server
- Client: You type
dockercommands - Server: Daemon runs in background as root (by default)
- How it works: Client asks daemon to do everything
Good: Centralized, handles multiple clients, mature ecosystem Bad: Always consumes resources, needs root by default, single point of failure
Podman: Direct Execution
- No daemon: Commands run directly via fork-exec
- Per-command: Each
podmaninvocation is its own process - Result: Nothing persistent running when you’re not using it
Good: Zero idle resources, no single point of failure, rootless by default Bad: Some Docker features work differently, smaller ecosystem
Resource usage
| When | Docker | Podman |
|---|---|---|
| Idle | ~50-100+ MB (daemon) | ~0 MB (no persistent daemon) |
| Running | Daemon + containers | Containers + short-lived conmon/pause processes |
| CPU | Always some baseline | Only when commands are active |
The numbers above are approximations. Docker’s daemon overhead gets amortized across many containers on a busy server. If you’re running 50 containers, the daemon cost is noise. On a laptop or a small VPS running two or three containers, Podman’s zero-idle model saves real memory.
Why the architecture matters beyond resources
The daemon vs daemonless distinction isn’t just about memory. It affects:
- Startup behavior: Docker’s daemon must be running before any container command works. If the daemon crashes, all container management stops. Podman commands are independent; one failing doesn’t affect others.
- System updates: Updating Docker requires restarting the daemon, which briefly interrupts all container management. Podman updates are just binary replacements. No service restart needed.
- Root access: The Docker daemon needs root by default. This means any user who can run
dockercommands effectively has root on the host (via the socket). Podman’s rootless model means container management doesn’t require root at all.
Security: Rootless Containers and Attack Surface
Podman wins on default security. Here’s why, and where Docker has caught up.
The core issue is Docker’s daemon architecture. The dockerd process runs as root by default and listens on a Unix socket (/var/run/docker.sock). Any process that can access that socket has effective root control of the host. This is why security guides tell you never to mount the Docker socket into containers. It’s equivalent to giving the container root on the host.
Podman has no daemon. Each podman command is a standalone process that forks, executes the container, and exits. There’s no persistent root process to target.
Default setup:
- Daemon runs as root
- Compromise the daemon, compromise the system
docker cphistorically had host-escape bugs
Rootless mode exists (since Engine 20.10):
- Not the default on Linux servers
- Extra setup required (uidmap, slirp4netns/pasta)
- Engine 29.5.0 made gvisor-tap-vsock the default rootless network driver, a real improvement
- Some features still limited in rootless (Swarm, certain network modes)
Rootless by default:
- Run containers as a normal user out of the box
- No persistent root process to exploit
- User namespace mapping: container root maps to your regular user
Architecture advantage:
- No daemon = no always-on root target
- Each command is isolated. One compromised container doesn’t hand you the daemon
Security Takeaway
Podman is safer by default. Docker can be hardened with rootless mode, but it requires extra setup and has tradeoffs. For a solo operator on a Linux VPS, Podman’s rootless-by-default model is one less thing to configure correctly.
If you’re running containers with non-root users inside the container (which you should), see our guide on adding users to Docker containers.
Modern CVE examples
The old go-to example was CVE-2019-5736 (runc container escape). It’s still relevant history, but 2025-2026 produced better examples:
Both Tools Share runc
The 2025 runc /proc write breakout family (CVE-2025-31133, CVE-2025-52565, CVE-2025-52881) affected both Docker and Podman. They share the runc runtime. Fixed in Docker Engine 28.5.2 and Podman 5.7.0. The takeaway: when a shared runtime component has a vulnerability, architecture (rootless vs root daemon) determines the blast radius.
Docker-specific 2026 issues: docker cp escape bugs (CVE-2026-41567/41568/42306, host-root code execution via archive decompression), seccomp AF_ALG issue (CVE-2026-31431), and a string of Docker Desktop CVEs including Model Runner vulnerabilities (CVE-2026-28400, CVE-2026-33990, CVE-2026-5817/5843).
Podman-specific 2026 issues: Env-leak CVE-2026-57231 (malformed Env entries leak host variables), build ADD/COPY escape CVE-2026-44517, and the Quadlet truncation bug CVE-2026-19730 (fixed in 6.1.0).
Both tools have CVEs. The difference: Podman’s daemonless, rootless-by-default architecture limits what an attacker can reach. A container escape in Podman lands you in a user namespace, not root on the host.
What this means in practice
For a solo operator running containers on a VPS, the security model matters more than any individual CVE. CVEs get patched. The architecture stays.
With Docker’s default setup, a container escape gives the attacker root on the host because the daemon runs as root. With Podman’s rootless model, a container escape gives the attacker access to a user namespace. Still bad, but significantly less bad than root on the host.
Docker’s rootless mode closes this gap, but it’s not the default and requires extra configuration (uidmap, networking setup, some features disabled). If you’re willing to do the work, Docker rootless is a real option. If you want secure defaults without configuration, Podman is the answer.
Performance: What the Benchmarks Really Say
Reality Check
No single authoritative benchmark exists for Docker vs Podman in 2026. Community testing shows differences are small at single-container scale. Pick based on security, features, and cost, not startup time deltas you won’t notice.
Here’s what we actually know:
| Metric | Docker | Podman | Notes |
|---|---|---|---|
| Startup | ~1-1.5s | ~0.8-1s | Podman edges it; difference is negligible for long-running services |
| Build speed | Fast (BuildKit) | Comparable (Buildah) | Both support multi-stage and caching |
| Idle memory | ~50-100+ MB (daemon) | ~0 MB (no daemon) | Matters on small VPS, not on busy servers |
| Rootless networking | ~5-8 Gbps (gvisor-tap-vsock) | ~8-10 Gbps (pasta) | Both far ahead of the old slirp4netns (~570 Mbps) |
| Disk usage | Higher with containerd image store (Engine 29 default) | Standard overlay | Real gotcha on small disks |
The rootless networking numbers are estimates from community testing (sanj.dev, June 2026; r/podman discussions), not lab benchmarks. Your mileage will vary with hardware and workload.
The one performance item that actually matters for operators: Docker Engine 29’s containerd image store can use more disk than overlay2 for the same images. On a 40 GB VPS root disk, that’s worth watching.
Build speed
Both tools build images fast enough that you won’t notice the difference in daily work. Docker uses BuildKit (integrated into the daemon since Engine 23). Podman uses Buildah (standalone, daemonless). Both support multi-stage builds, layer caching, and parallel build stages.
Where build speed matters: CI pipelines building large images with many layers. In practice, the bottleneck is usually network I/O (pulling base images) or compile time, not the container build tool itself.
Container density
On a busy server running dozens of containers, Docker’s daemon overhead gets amortized to near-zero per container. Podman’s per-command model means each container has a small conmon process, but these are lightweight. At high container density (50+ containers), the difference is negligible. The real constraint is always the application workload, not the container runtime.
Cost & Licensing: Docker Desktop and Docker Hub
This is the section most comparison articles skip, and it’s the one that matters most if you’re paying for anything. The licensing model is the single biggest difference between the two tools from a business perspective — Docker has one, Podman doesn’t.
Docker Desktop License
Docker Desktop is free for: personal use, education, non-commercial open source, and small businesses (fewer than 250 employees AND less than $10M annual revenue). If you exceed either threshold, you need a paid subscription. The Docker Engine and CLI are Apache-2.0 and always free — you only need a license for Desktop (the GUI + VM manager).
Docker pricing (Aug 2026)
| Plan | Price | Docker Hub Pulls | Desktop Included |
|---|---|---|---|
| Personal | $0 | 200 pulls/6 hours | Yes (free-tier limits) |
| Pro | $9/user/month (annual) | Unlimited | Yes |
| Team | $15/user/month (annual) | Unlimited | Yes |
| Business | $24/user/month | Unlimited | Yes |
Pro was $5 before the December 2024 price increase. Team went from $9 to $15. Prices move — verify on docker.com/pricing before committing.
Docker Hub pull limits: Pull consumption charges were cancelled starting April 1, 2025. Paid plans get unlimited pulls. The free Personal tier gets 200 pulls per 6 hours (the docs say this; the pricing page says “100 pulls/hr” — there’s a discrepancy, so check the docs). Unauthenticated pulls are limited to 100 per IPv4 per 6 hours.
For self-hosters running a handful of containers, these limits are rarely a problem. Where it hits: CI pipelines that pull images frequently, or teams running many services that restart often. The fix is simple — authenticate your pulls (doubles your limit) or mirror through GHCR or a self-hosted registry.
Docker also offers Docker Hardened Images (DHI) — minimal base images with near-zero CVEs, SBOM and SLSA L3 provenance. The free tier is useful for security-conscious deployments; the paid Select tier starts at $5k/repo (enterprise only).
Podman: Fully open-source (Apache-2.0), CNCF Sandbox project, no licensing restrictions. Use it however you want. No per-seat pricing, no revenue thresholds, no pull limits. If you’re running containers on a VPS, the only cost is the server itself — affordable VPS hosting like Hetzner or budget VPS options like Hostinger keeps that under €5/month for a small setup.
- Running containers on a VPS? The engine is always free for both tools. Docker Desktop licensing only matters on workstations.
- CI/CD tip: Authenticate your Docker Hub pulls in CI (
docker login) — anonymous limits are tighter. Or pull through GHCR or a self-hosted registry to avoid Hub limits entirely. - Budget VPS hosting like Hetzner or Hostinger keeps your container hosting costs low — the engine choice won’t affect your hosting bill.
Compose: Docker Compose vs Podman Compose
Docker Compose is the industry standard for defining multi-container apps. It’s mature, well-documented, and everywhere. If you’re running multiple services that need to talk to each other (web app + database + cache + reverse proxy), Docker Compose is how most people define that stack.
Podman’s compose story has improved. podman compose is now a wrapper that can invoke the real docker-compose binary (if installed) or fall back to podman-compose (a Python reimplementation). The podman-compose project tracks Docker Compose features via a compatibility spreadsheet — common cases work, edge cases may need tweaking.
The practical advice: if you’re on a Linux server with systemd, consider whether you need compose at all. Quadlet (covered in the next section) gives you systemd-native container management without the compose layer. For development workstations, Docker Compose remains the path of least resistance.
- Mature, full-featured, industry standard
docker compose up -djust works for most files- Secrets management support (see managing secrets in Docker Compose)
- Works with Docker Desktop on all platforms
podman composecan invoke realdocker-compose— best of both worlds- podman-compose covers common cases; complex files may need tweaks
- On systemd Linux hosts, Quadlet is the recommended alternative (see next section)
- No daemon dependency — each compose invocation is standalone
Compose Compatibility
If you have complex Docker Compose files with build contexts, multiple networks, or advanced features, test them with podman compose before switching. Using the wrapper with the real docker-compose binary avoids most issues. For Linux servers with systemd, Quadlet is often a better fit than either compose tool.
Podman Quadlet: Containers as systemd Services
This is the feature that makes Podman the right choice for self-hosted Linux servers. Quadlet lets you define containers as systemd unit files — systemd manages the lifecycle (start, stop, restart on boot, logging) without needing Docker’s daemon or compose.
If you’ve ever written a systemd service file, you already know how Quadlet works. You define a .container file, systemd picks it up, and you manage it with systemctl like any other service.
Here’s a real example:
# /etc/containers/systemd/myapp.container
[Unit]
Description=My nginx app
[Container]
Image=docker.io/library/nginx:1.27
PublishPort=8080:80
Volume=myapp-data:/usr/share/nginx/html
AutoUpdate=registry
[Service]
Restart=always
[Install]
WantedBy=default.target
Then:
systemctl daemon-reload
systemctl start myapp
systemctl status myapp # verify it's running
journalctl -u myapp -f # follow logs
List all Quadlet units with podman quadlet ls.
Why Quadlet?
systemd manages the container lifecycle — restart policies, boot ordering, log aggregation via journald — without a persistent daemon or compose overhead. This is how you run containers in production on a Linux VPS. Docker has no native equivalent (you’d use third-party systemd generators or compose systemd units).
New in Podman 6: reworked install (tracks files in subdirectories), UID=/GID=/Options= keys on volumes, AppArmor key, and ImageVolume= in 6.1. If you’re running self-hosted server panels or any long-running service on a Linux box, Quadlet is worth learning.
Quadlet vs Docker Compose for production
For a solo operator running services on a Linux VPS, the choice comes down to what manages the lifecycle:
- Docker Compose: You run
docker compose up -dand hope it stays running. For boot persistence, you need a systemd unit that calls compose, or a restart policy on each container. Logging goes to Docker’s log driver. - Quadlet: systemd owns the container lifecycle natively.
Restart=alwaysis a systemd directive. Logs go to journald. Boot ordering works withAfter=andWants=. No daemon, no compose binary, no wrapper scripts.
If you’re already using systemd for everything else on your server (and you should be), Quadlet containers fit right in. One more systemctl status to check, one more journalctl -u to follow logs. No new tooling to learn.
Upgrading: Podman 6 Is a Migration, Not a Patch
Breaking Changes
Podman 6 is not a drop-in upgrade from 5.x. It removes several subsystems entirely. If you’re running Podman 5 on production servers, read this before upgrading. The upgrade is more like moving from Python 2 to 3 than a routine patch — the API surface changed, legacy backends are gone, and some workflows need adjustment.
What Podman 6 removed
- BoltDB — replaced by SQLite (auto-migration happens on reboot from Podman 5.8+)
- slirp4netns — replaced by pasta (default since 5.0; now the only option)
- CNI — replaced by Netavark (default since 4.0; now the only option)
- cgroups v1 — cgroups v2 required
- iptables — nftables only
- Intel Mac support — stay on Podman 5.x if you have an Intel Mac
- Windows 10 — Windows 11 required
Pre-upgrade checklist
- Confirm cgroups v2:
stat -fc %T /sys/fs/cgroupshould returncgroup2fs - Stop all
podman machineVMs before upgrading - On Hyper-V: run
podman machine resetbefore the upgrade - Check for CNI or slirp4netns references in your configs
podman volume prunesemantics changed (now Docker-like: only anonymous volumes; use--allfor the old behavior;--dry-runto preview)- Linux
podman machineVMs must be recreated after upgrade (volume mounts now use systemd)
Verify after upgrade
podman info --format '{{.Version}} {{.Host.Security}} {{.Host.NetworkBackend}}'
# expect: 6.x, rootless, netavark
podman system check
# storage/DB integrity check
stat -fc %T /sys/fs/cgroup
# should return: cgroup2fs
Podman Desktop 1.29 (July 2026) supports Podman 6 and recommends wiping data on 5-to-6 upgrades.
What the migration looks like in practice
On Fedora or RHEL, the upgrade is typically a package manager operation:
# Fedora
sudo dnf upgrade podman
# Check the version
podman --version
# expect: podman version 6.x.x
The BoltDB to SQLite migration happens automatically on reboot if you’re coming from Podman 5.8+. If you’re on an older 5.x release, upgrade to 5.8 first, reboot, then upgrade to 6.
The biggest pain point in practice: podman volume prune. In Podman 5, it pruned all unused volumes. In 6, it matches Docker’s behavior — only anonymous volumes. Use podman volume prune --all for the old behavior, and --dry-run to preview what would be deleted.
Migrating from Docker to Podman
If you’re moving from Docker to Podman on a Linux server, the CLI is mostly compatible. The basic commands are identical — run, build, ps, images, exec, logs. The differences show up in the details: networking, volumes, and tooling integration.
The migration is usually straightforward for simple setups. For complex environments with many services, CI pipelines, and tooling that depends on Docker-specific features, plan for a day of testing.
# The simplest migration
alias docker=podman
# Test your containers
podman run -d --name test nginx
podman ps
podman logs test
Socket compatibility
Many tools (Testcontainers, VS Code Dev Containers, CI scripts) expect a Docker socket. Podman can provide one:
systemctl enable --now podman.socket
# Option 1: symlink
ln -sf /var/run/podman/podman.sock /var/run/docker.sock
# Option 2: environment variable
export DOCKER_HOST=unix:///var/run/podman/podman.sock
Watch out for
Migration Gotchas
host.docker.internal(Docker) vshost.containers.internal(Podman) — different hostnames for reaching the host from inside a container- Rootless port publishing: ports below 1024 need extra configuration (or run as root)
- Volume permissions with user namespaces/uidmap — files created by root inside the container may appear owned by a high-numbered UID on the host
- Compose files with advanced features may need tweaks for podman-compose
- Audit scripts that hardcode
docker.sockpaths before switching
For a deeper dive on using containers safely for AI workloads, see running AI CLI tools safely in Docker or Podman.
CI/CD compatibility
Both GitHub Actions and GitLab CI support Podman. GitHub Actions has Podman, Buildah, and Skopeo container jobs available. This matters for security: with Podman, you don’t need Docker-in-Docker (DinD) or privileged containers in CI — each build step runs as a standalone process. No daemon-in-daemon, no privileged mode, no Docker socket exposure in your pipeline.
If you’re running GitLab CI with Docker, the standard approach uses a privileged DinD container. With Podman, you can run rootless builds without privileged mode. The tradeoff: you need to set up Podman in your CI runner, which adds configuration. For most teams, Docker in CI is already working and the migration cost isn’t worth it unless security is a hard requirement.
AI Workloads: Docker Model Runner vs Podman AI Lab
Both tools now support running AI models locally in containers, but they take different approaches. This is a fast-moving area — both Docker and Podman shipped major AI features in 2025-2026, and the landscape will keep shifting. If you’re evaluating containers for AI workloads, the choice depends on your hardware and whether you’re already invested in one ecosystem.
- GA since September 2025
- LLMs packaged as OCI artifacts on Docker Hub
- llama.cpp backend with OpenAI-compatible API (
http://localhost:1234/v1) - Works on Docker Desktop (Apple Silicon, NVIDIA, ARM) and Linux via Docker CE
- Compose
models:top-level key support - Deeper productization — models are first-class Docker artifacts
- Extension for Podman Desktop
- Ships with Podman Desktop — fully self-contained
- Podman 6.0 added AMD GPU support to
--gpus(previously NVIDIA-only) - No separate install beyond Podman Desktop
- Less productized than Docker’s approach, but no vendor lock-in
GPU Containers
Both tools support NVIDIA GPUs. Podman 6 added AMD GPU support via --gpus, which is significant if you’re running AMD hardware. For practical local inference, you can also self-host Ollama with Docker Compose — it works with both engines.
Both are free and evolving fast. Docker’s Model Runner is more polished for the “pull a model, run it” workflow. Podman AI Lab is simpler if you’re already on Podman Desktop. Neither requires a paid subscription for local inference.
Which to pick for AI workloads
If you’re running local LLMs on a Mac or Windows workstation, Docker Model Runner is the more mature option — the OCI-packaged models on Docker Hub and the OpenAI-compatible API make it easy to integrate with existing tools. The Compose models: key lets you define models alongside your services.
If you’re on Linux and already using Podman, AI Lab gives you a self-contained experience without pulling in Docker Desktop. The AMD GPU support in Podman 6 is a real differentiator if you’re running AMD hardware — Docker’s --gpus support has historically been NVIDIA-first.
For production AI inference on a VPS, neither tool is the answer — you’d use something like Ollama with Docker Compose or a dedicated inference server. The Model Runner and AI Lab features are primarily for local development and experimentation.
Which Container Tool Should You Choose?
The decision comes down to your priorities: ecosystem size, security defaults, licensing cost, and where you’re running containers.
Choose Docker When:- Learning containers: Better docs, more tutorials, easier to start
- On Windows or Mac: Docker Desktop is convenient (mind the license if you’re at a larger org)
- Need the ecosystem: Tools, integrations, cloud support — Docker is everywhere
- Team already uses it: Migration cost isn’t worth it if Docker works for you
- Docker Swarm: If you’re using Swarm for orchestration
- Building a home server: The best Docker containers for a home server ecosystem is massive
- Security matters: Rootless by default, no daemon, smaller attack surface
- Linux shop: Works great on Linux, especially with systemd and Quadlet
- Going to Kubernetes: Podman pods map directly to Kubernetes pods
- Resource conscious: Zero memory when idle, no daemon overhead
- Red Hat / RHEL stack: Ships as default on Fedora and RHEL
- Cost-sensitive: Fully open-source, no licensing restrictions — deploy on a Linux VPS with affordable VPS hosting and no surprise bills
Start with Docker. Better learning materials, more community help, Docker Desktop gives you a GUI. You can always switch to Podman later once you understand the basics. The best Docker containers for a home server ecosystem is massive and well-documented.
Use Podman. Rootless by default is a real advantage. No daemon running as root means less attack surface. Security teams and compliance auditors appreciate it. If you’re deploying on a Linux VPS, Podman with Quadlet gives you systemd-native container management with no licensing strings attached.
Use both. Docker for dev on Windows/Mac. Podman for production on Linux servers. OCI format means containers built on one engine run on the other. This is what I do — Docker Desktop on Mac for development, Podman with Quadlet on Linux VPS for production. The alias docker=podman trick makes the transition seamless on the server side.
Common Commands
The basic commands are identical between Docker and Podman. This is by design — Podman was built as a drop-in replacement for Docker’s CLI.
# These work identically with docker or podman
docker run -d --name web nginx # Background container
docker build -t myapp . # Build image
docker ps # List running containers
docker images # List images
docker exec -it web bash # Shell into container
docker logs web # View container logs
docker compose up -d # Start compose stack
# Podman-specific
podman machine init # Create a VM (Mac/Windows)
podman machine start # Start the VM
podman machine stop # Stop the VM
podman pod create --name mypod # Create a pod
podman pod ps # List pods
podman generate kube mypod > pod.yaml # Export as Kubernetes YAML
podman quadlet ls # List Quadlet units
podman system check # Check storage integrity
podman system reset # Reset all Podman data (destructive)
The podman machine commands are only relevant on Mac and Windows — they manage the Linux VM that Podman runs in. On Linux, Podman runs natively.
Verification Commands
# Check Docker version and config
docker version --format '{{.Server.Version}}'
docker info --format '{{.Driver}} {{.FirewallBackend}}'
# Check Podman version and config
podman info --format '{{.Version}} {{.Host.Security}} {{.Host.NetworkBackend}}'
podman system check # Storage/DB integrityFor the full command reference, see 60+ must-know Docker commands.
Verifying your setup
After installing or upgrading, verify everything is working:
# Docker
docker version --format '{{.Server.Version}}' # expect 29.x
docker info --format '{{.Driver}} {{.FirewallBackend}}' # check storage driver and firewall
# Podman
podman info --format '{{.Version}} {{.Host.Security}} {{.Host.NetworkBackend}}'
# expect: 6.x, rootless, netavark
podman system check # storage/DB integrity
Troubleshooting & Gotchas
These are the issues operators actually hit in production. Not theoretical — these come from community reports, GitHub issues, and forum discussions.
Containerd Image Store Disk Usage
Docker Engine 29 made the containerd image store the default for fresh installs. Community reports indicate it can use more disk than overlay2 for identical image sets (duplicated compressed base layers). On a small VPS, this matters.
Check if you’re using it: docker info --format '{{.Driver}}'
Opt out (existing installs keep legacy by default; fresh installs get containerd): edit /etc/docker/daemon.json:
{ "features": { "containerd-snapshotter": false } }Check disk usage: docker system df shows how much space images, containers, and volumes are using. Compare with du -sh /var/lib/docker/ to see the actual on-disk footprint.
If you’re running low on disk, see reclaiming disk space from /var/lib/docker/overlay2.
Docker Networking Changes (28/29)
Docker Engine 28.0.0 rewrote the iptables networking rules. Some operators hit issues with ipset kernel requirements, random MACs on container interfaces, and changed port-publishing behavior. Engine 29 added experimental nftables support (dockerd --firewall-backend=nftables) — not production-ready yet, but it’s coming.
Verify your firewall backend: docker info --format '{{.FirewallBackend}}'
If Docker is bypassing your firewall rules, see fixing Docker that bypasses your firewall. This is a common gotcha — Docker manipulates iptables directly, which can conflict with UFW or firewalld rules.
Socket Compatibility
Tools that depend on docker.sock (Testcontainers, VS Code Dev Containers, many CI scripts) can work with Podman via socket activation:
systemctl enable --now podman.socket
# Option 1: symlink (works but environment variable is cleaner)
ln -sf /var/run/podman/podman.sock /var/run/docker.sock
# Option 2: environment variable (preferred)
export DOCKER_HOST=unix:///var/run/podman/podman.sockWatch out for host.docker.internal (Docker) vs host.containers.internal (Podman) — different hostnames for reaching the host from inside a container. Scripts that hardcode the Docker hostname will break.
Test your socket setup:
curl -s --unix-socket /var/run/podman/podman.sock http://localhost/_ping
# Should return: OKRootless Port & Volume Gotchas
- Privileged ports: Rootless containers can’t bind to ports below 1024 by default. Use
sysctl net.ipv4.ip_unprivileged_port_start=80or publish to a higher port and proxy. - uidmap: Files created by root inside a rootless container map to a high-numbered UID on the host. This causes permission issues with bind mounts. Check
/etc/subuidand/etc/subgidfor your user. - Volume permissions: If a container writes as root to a bind mount, the files are owned by your user’s mapped UID, not root. Plan your volume strategy accordingly.
Quadlet Truncation Bug (CVE-2026-19730)
Podman 6.0 had a bug in podman quadlet install --replace: replacing a longer unit file with a shorter one left trailing garbage from the old file. This caused silent failures — the generated systemd unit would have corrupted content. Fixed in Podman 6.1.0.
If you’re iterating on Quadlet files, check the generated units after each change:
systemctl daemon-reload
systemctl cat myapp.service # verify the generated unit looks correctFinal Word
Both tools work. Both are actively maintained. Both run OCI containers. The differences are real but they’re not blockers — you can ship production software with either one.
Docker is the safer choice for learning, Windows/Mac development, and teams that need the biggest ecosystem. The licensing cost only hits larger organizations — for personal and small-business use, Docker Desktop is free. The ecosystem is unmatched: every cloud provider, every CI system, every tutorial assumes Docker first.
Podman is the better choice for Linux servers, security-conscious deployments, and anyone who doesn’t want a root daemon running 24/7. Quadlet makes it especially good for self-hosted services managed by systemd. The CNCF governance gives it long-term credibility beyond Red Hat’s sponsorship.
The Bigger Picture
Docker and Podman aren’t the only options. containerd with nerdctl provides a Docker-compatible CLI backed by the containerd runtime (which Docker Engine 29 now uses internally). Rancher Desktop (still actively maintained as of August 2026) gives you a Docker-compatible environment on Mac and Windows with Kubernetes built in. The ecosystem is bigger than two tools.
I use Docker on my Mac for development because Docker Desktop is convenient. I use Podman on Linux servers because I don’t want a root daemon running and Quadlet fits my systemd workflow.
Pick what fits your situation. You can always switch later — OCI compatibility means your containers run on either engine. The important thing is to pick one, learn it well, and ship your software. The container engine is plumbing — your users don’t care which one you use.
Looking for containerized apps? Check out toolhunt.net’s self-hosted section.


