Table of Contents
Rootless container engines in practice
Podman and Docker are both tools for working with containers, but they differ in design, security model, and how they integrate with the rest of the system. This chapter focuses on those differences and on how to choose and use each tool effectively once you already understand the fundamentals of containerization and Docker basics from earlier material.
Architectural differences
Docker uses a classic client server model. The docker command is a client that talks to the Docker daemon, usually dockerd, over a Unix socket such as /var/run/docker.sock. The daemon runs in the background and typically has root privileges. All container lifecycle operations are requested by the client and carried out by the daemon.
Podman, in contrast, is daemonless for regular container work. The podman command talks directly to the underlying container runtime libraries and kernel interfaces. There is no always running root daemon for normal use. For some features, for example providing a Docker compatible remote API, Podman can run a small service, but this is optional and not required for basic container tasks.
The difference matters for how processes appear on the system. With Docker, most containers are child processes of the dockerd daemon. With Podman, each container process is directly visible as a child of the user or a small helper process, which can make process inspection and debugging slightly more straightforward, since the container processes look like regular processes in tools such as ps and top.
Rootful vs rootless operation
Docker was designed originally as a root managed service. Traditional Docker workflows assume that the daemon has root level access to manage images, networks, mounts, and namespaces. To allow non root users to control containers, systems usually add those users to a docker group. Membership in this group effectively grants abilities close to root, since the user can instruct the daemon to perform privileged operations.
Podman was designed with rootless containers as a primary feature. By default, a regular user can create and run containers without gaining broad root like rights over the host. Podman uses user namespaces and other kernel features to map container root to an unprivileged range of user IDs on the host. Inside the container, the user with ID 0 appears to be root, but on the host this maps to non root IDs, which limits what a compromised container can do.
Both tools can run containers as the real root user, sometimes called rootful mode. In rootful mode, Podman and Docker are similar in the level of power they have, but the way they provide that power still differs because Podman does not require a root daemon to stay running.
Running containers as real root increases risk. Prefer rootless Podman or carefully restricted Docker setups whenever possible, especially on multi user or shared systems.
Rootless Docker also exists through an additional setup called rootless mode. However, this came later and is not the default on many systems. Podman, on most distributions that support it, is ready for rootless use without extra configuration.
Pods and orchestration style
Podman introduces the concept of a pod as a first class object. A pod groups one or more containers that share namespaces such as network or IPC, similar in spirit to Kubernetes pods. With Podman, you can create a pod, assign ports and network configuration to it, and then add multiple containers that all live within this shared context.
Docker can run multiple containers and you can connect them with user defined networks, but the idea of a pod is not built into the base tool. Instead, Docker users commonly create multi container applications using a higher level tool such as Docker Compose, which uses a YAML file to define services, networks, and volumes.
This design difference influences workflows that aim to resemble Kubernetes closely. With Podman, it is possible to export and import pod definitions that are compatible with Kubernetes manifests in a basic way. This makes Podman attractive for developers who want local setups that map conceptually to Kubernetes pods without requiring a complete cluster.
Command line compatibility
Podman aims to be a drop in replacement for most common Docker workflows at the command line. Many Docker commands have direct Podman equivalents. In many cases you can change docker to podman in a command and expect similar behavior.
For example, to build an image with Docker you might use:
docker build -t myapp:latest .With Podman, a very similar command works:
podman build -t myapp:latest .Running a container interactively is also nearly identical:
docker run -it --rm alpine sh
podman run -it --rm alpine shThere are differences though, especially around features that relate tightly to the Docker daemon, the remote API, and volume or network handling. Some advanced flags or options may behave differently or not exist in Podman. Because of this, scripts that assume Docker semantics might require small adjustments before they work reliably with Podman.
Image formats and registries
Both Podman and Docker use the same fundamental container image formats that follow the Open Container Initiative specifications. Images pulled with either tool are typically compatible across engines. An image built with Docker can usually run unchanged with Podman, and vice versa, as long as the underlying architecture and OS match.
Registry interactions also look similar. To pull an image from a registry:
docker pull nginx:latest
podman pull nginx:latestAuthentication mechanisms, tags, and naming conventions work in very similar ways, since they are determined mostly by registry standards and not by the engine itself.
Podman stores images using libraries that originated in the container tools ecosystem associated with certain Linux distributions. Docker uses its own storage drivers integrated into the daemon. The underlying storage locations and driver implementations differ, but these details are mostly invisible in everyday use. However, it does mean that Podman and Docker typically do not share the same local image store by default. If you use both on the same host, each will manage its own set of pulled and built images unless you deliberately configure shared storage, which is a more advanced topic.
Service management and integration with systemd
Since Docker uses a root daemon, it is usually started and managed with the system service manager as a single long lived service. This makes it easy to ensure that the Docker engine itself is running on boot, but the container lifecycle is tied to this central daemon process. To run containers at boot with Docker, you either rely on Docker’s own restart policies or on separate service management that talks to the daemon.
Podman fits more directly into per container service management models. Because each container runs without requiring a central daemon, Podman can generate native service unit files for the system service manager. This allows each container, or pod, to be represented as an individual service with its own dependencies and restart rules.
For example, Podman can generate a service definition and integrate it with the system service manager so that a container starts at boot, restarts on failure, and is monitored in the same way as other system services. This approach aligns container lifecycle more closely with how other services are handled on the system.
Remote APIs and tooling ecosystem
The Docker daemon exposes a well known HTTP API. Many third party tools, graphical interfaces, continuous integration systems, and orchestration utilities talk directly to this API to build, run, and manage containers. Because this API is so widely adopted, Docker often has first class support in external tooling.
Podman did not originally include such a remote API, since it focused on local daemonless operation. As adoption grew, Podman introduced a Docker compatible API through a helper service. This service can listen on a socket and accept Docker style API requests. Tools that expect a Docker endpoint can sometimes use Podman instead if they are pointed at the Podman service socket.
Since the Podman API is compatible with Docker in many areas but not perfectly identical everywhere, some complex or low level tools may still assume behaviors specific to the Docker daemon. For basic build and run tasks, compatibility is usually enough, but specialized or older tools may require Docker to be installed to function as intended.
Security considerations
Podman’s emphasis on rootless operation gives it an advantage in many security focused environments. When each user can run containers under their own user identity, and container root is mapped to unprivileged host IDs, a break out from a container tends to have more limited impact. Podman also leverages security technologies such as user namespaces in a way that is natural to its design.
Docker’s root daemon can be a larger target. If an attacker gains control of the Docker socket, they can instruct the daemon to start privileged containers, mount host directories, and perform other powerful actions. For this reason, giving access to the Docker group is often treated as equivalent to granting root level privileges.
Both engines support additional security controls, such as seccomp profiles and mandatory access control systems configured by the underlying distribution. The difference is mainly in the default posture. Podman’s defaults favor individual user isolation and minimal central privilege, while Docker’s defaults are oriented around a central root level service for convenience and broad compatibility.
Performance and resource usage
Because both Podman and Docker rely on the same kernel features, such as namespaces and cgroups, raw container performance is generally similar. An application running in a container built by Podman should perform much like the same application running in a Docker container, given comparable configuration.
The presence or absence of a long running daemon can influence resource usage slightly. Docker keeps the daemon process running even when no containers are active, which consumes some memory and CPU overhead, although typically small on modern systems. Podman does not need such a daemon for basic use, which can reduce idle resource consumption.
In practice, for most users, performance differences between Podman and Docker are not the primary reason to choose one or the other. The security model, ecosystem compatibility, and administrative style tend to matter more.
Migrating Docker workflows to Podman
Because Podman strives for command line and image compatibility, many Docker workflows can be adapted by changing command names and adjusting a few behaviors.
A straightforward pattern is to replace docker with podman in common commands such as build, run, ps, logs, and exec. For example, a script that runs:
docker build -t myimage .
docker run -d --name mycontainer myimagecan often be changed to:
podman build -t myimage .
podman run -d --name mycontainer myimageHowever, the surrounding environment may need attention. If the script assumes the Docker daemon is always running, you no longer need to ensure that for Podman. If the script uses Docker specific networking options or mount behaviors, you must verify how Podman interprets those options.
For tools that talk to the Docker remote API, migrating to Podman requires setting up the Podman API service and configuring tools to talk to its socket. In many development environments, this is sufficient to reuse most Docker oriented tooling while running Podman underneath.
Choosing between Podman and Docker
The choice between Podman and Docker depends on priorities and environment.
On personal machines and developer laptops that already rely on tools specifically built for Docker, staying with Docker may be simpler. Its widespread adoption and extensive documentation mean that examples and guides often assume Docker is available. Continuous integration services and cloud platforms also frequently provide Docker by default.
On systems where security and least privilege are critical, for example multi user servers and shared lab environments, Podman’s rootless design can be attractive. The ability for each user to manage own containers without gaining system wide administrative power aligns with traditional Unix multi user principles.
In environments that closely follow Kubernetes models, Podman’s pod feature and its ability to represent container groups in a way that resembles Kubernetes pods can be useful. It can support workflows where developers prototype locally with Podman pods before deploying to a full cluster.
In some cases, using both tools on the same host is reasonable, with Docker supporting existing tooling that is tightly coupled to its API and Podman serving new, more security conscious or Kubernetes styled use cases. Care must be taken in such setups, since they will not share image storage by default and may require explicit decisions about which engine is responsible for which workloads.
By understanding these differences, you can select the container engine that best fits each situation rather than treating them as interchangeable in all respects.