Podman has no background daemon while Docker relies on dockerd running as root — what specific operational and security consequences follow from that architectural difference, and what common Docker workflows break as a result?
Quick Answer
Docker's dockerd is a persistent, typically root-owned daemon that owns every container's lifecycle, so if the daemon dies or is compromised, every container on the host is affected at once; Podman instead forks each container as a direct child process of the user who ran podman run, so containers survive independently and a compromised container doesn't inherit root daemon privileges. The main workflows that break are anything relying on the Docker socket being present, like Docker-in-Docker CI runners or tools that bind-mount the socket for container introspection.
Detailed Answer
Docker is like an apartment building with one building superintendent, the daemon, who holds every tenant's spare key and personally manages every unit's plumbing, mail, and locks — if the superintendent quits or gets held hostage, every apartment is affected. Podman is more like a set of standalone houses: each container is its own independent household managed directly by its owner, with no single building-wide manager whose failure or compromise takes down everyone else.
Docker's architecture centers on dockerd, a long-running background process, traditionally running as root, that owns the container runtime, image store, networking, and the API socket the docker CLI talks to. This was simple to build and made features like build caching and centralized logging easy, but it concentrates enormous privilege in one process: anyone with access to docker.sock effectively has root on the host, because Docker will happily let you bind-mount / into a privileged container. Podman was designed specifically to remove that single point of privilege — there's no daemon at all; the podman CLI itself forks the container as a subprocess of your own user session using Linux namespaces, so a rootless podman run never touches root privileges anywhere in the chain.
When you run podman run -d --name checkout-worker nginx, Podman creates a new user namespace mapping your unprivileged UID to UID 0 inside the container, so "root" inside the container is not root outside, sets up network and mount namespaces, and then forks and detaches the container process as a child of a lightweight conmon (container monitor) process rather than a central daemon — conmon stays alive to hold the container's stdio and exit code even if the parent podman process or your shell exits. Because there's no daemon tracking state centrally, Podman reconstructs container state by reading from local files under the user's home directory and querying the kernel directly each time you run a command.
In production, this means a Podman host loses the "one daemon crash kills every container" failure mode entirely — each container is only as fragile as its own conmon process. What to monitor instead: conmon process health per container, storage driver behavior since fuse-overlayfs, used for rootless storage, has different performance characteristics than the daemon-managed overlay2 driver Docker uses and can be slower for write-heavy workloads, and subuid/subgid range exhaustion on hosts running many rootless containers for different users, since each user needs a large enough allocated UID range in /etc/subuid.
The gotcha most teams hit during migration is CI tooling that assumes docker.sock exists — Docker-in-Docker patterns, the original docker-compose, and tools that bind-mount the socket to introspect sibling containers all silently fail under Podman because there is no socket by default. Podman does offer an optional API socket via podman system service that emulates the Docker API for compatibility, but running that service reintroduces a long-lived privileged process, which quietly defeats the daemonless security model teams often migrate to Podman specifically to get.