Docker Vs Podman

Docker has been synonymous with containers for a number of years now. Almost all containers use the runc low-level container runtime (or its c-based clone crun) which can trace its history back to the initial development in-house at Docker though it has since been transferred to the open container initiative – OCI.

Docker now also uses the open-source high-level container runtime daemon ‘containerd’ (also open-sourced by Docker). In many cases when a user issues a Docker CLI (command line interface) instruction like

docker run …

The docker CLI passes the command to containerd to perform. Where necessary it can create, or pass instructions to, an instance of the container runtime ‘runc’.

Containerd however is seen as having poor security. It is a daemon process that runs as root on Linux systems. This means that when a container is created it will also run as root and have root privileges. If a process executing inside a container should manage to break out it will find itself with the access of the root user on the host.

Diagram comparing the different components of Docker and Podman.

Podman was created to avoid this situation. It is “deamonless”. When a user requests a container is created, the new container will run with that user’s privileges. That does mean that it cannot use the full power of user root (without using the “–privileged” option). Normal users cannot map to TCP port below 1024 and host file system access is not assured.

Comparing Operation

The podman command has been written to be a direct replacement for the docker CLI so if you are used to issuing the command

docker run -it –rm ubuntu:latest /bin/bash

the podman equivalent would be

podman run -it –rm ubuntu:latest /bin/bash

or

docker image list → podman image list
docker container list –all → podman container list --all
docker container stop <ctrId> → podman container stop <ctrId>

Comparing Image Formats

Both Docker and Podman use OCI-formatted images so the images build by one cab also be run by the other. Under the hood, Podman uses the ‘buildah’ build tool but “podman build …” still works as before. Podman expects a Dockerfile to be named Containerfile.

Comparing Host Processes

If you list the active processes before and after starting a container and then run the ‘diff’ command on the two processing lists you can see what processes were created for the newly started container.

Docker

Command line output showing Linux processes run by Docker.

With Docker, “/usr/bin/containerd-shim-runc-v2” (the containerd wrapper of runc) is started which in turn starts the container command: in this case “/usr/sbin/httpd”. These all run as root. The container command starts 5 httpd processes within the container. If an attacker was able to take over the container command they would be executing as root on the host system.

Podman

Command line output showing Linux processes run by Podman.

With podman, a network configuration utility “/usr/bin/slirp4netns” has a processes started. “conmon” (a container monitor utility that calls runc) is also started to run the container which in turn starts the container command: “/usr/sbin/httpd” as above. All these process execute as “user1” (That is the user the executed the podman run command) not root. As above, the container command starts 5 httpd processes within the container which all execute using the temporary internal user UID 100099.

If an attacker was able to take control of the container command they would only have the privileges of “user1”. More robust but still not without opportunities.