Mastodon

Day 6: Podman Containers alternative to Docker

Table of contents

Containers INtroduction

If Day 5 of 100 days of FullStack DevOps was KVM Virtualization, Day 6 is about containers with Podman. Usually on a VM or VPS (we’ll get to it on day 7!) we want to run software, if we can’t run self contained apps directly under systemd (or your favorite init system) we’ll have to consider running our software in containers for ease of use. We’ll get back to virtualization automation in future days.

For a long time, “Docker” was synonymous with “Containers.” However, containers or linux namespaces which are the underlying feature Docker, Podman and other containerization technologies use, have been in existance since 2002, that’s 11 years before docker even existed. LXC was a leader in linux containers. As we lean into the philosophy of Sovereign Engineering, we need tools that respect the OS, follow standard security models, and don’t rely on a single “all-powerful” daemon.

Thus we’ll be demonstrating Podman.

Originally developed by Red Hat and written entirely in Go, Podman isn’t just a Docker clone; it’s a fundamental rethink of how containers should behave on a Linux system.


Why Podman? Breaking the Daemon Monopoly

The biggest architectural difference is that Podman is daemonless.

When you run a command in Docker, you are talking to the Docker Daemon (dockerd) which runs as root. If that daemon dies, your containers can get orphaned. If that daemon is compromised by a security issue, the attacker has the keys to your entire kingdom. Talking about CopyFail CVE-2026-31431 this is a big problem.

Podman follows the “Fork/Exec” model, similar to how your shell works. When you run a container, Podman starts a process directly. This makes it OCI (Open Container Initiative) compliant and much more resilient to existing problems.

Installing Podman

To install podman you can follow the instructions on https://podman.io/docs/installation for your operating system If on debian, you can always run

sudo apt install podman

However, it will likely have a outdated version of podman.

You can download the installer from https://github.com/containers/podman/releases. For linux you just run 1 single binary which takes care of everything

PODMAN is also available on FreeBSD 14.3 and newer! Where docker is NOT avilable, so if you use FreeBSD podman is the way to go for containers.

Dropin alias Docker - Podman

After you’ve insstalled Podman you can easily do an alias like

alias docker=podman

And you won’t even notice it;)

The Ecosystem: Buildah, Skopeo, and Podman-compose

Podman is part of a modular “Swiss Army Knife” for containers which are meant to provide some alternatives to some docker functionalities. Keep in mind that podman is a drop in replacement for docker, meaning you can use Dockerfiles just fine, however, there are some other specific tools you can use such as:

  • Buildah: A tool specialized in building images. It allows you to build OCI images without needing a full container engine running.
  • Skopeo: A powerhouse for inspecting, copying, and signing images across different registries without having to “pull” them locally first.
  • Podman-compose: The seamless transition for those coming from the Docker-compose world.

The Killer Feature: Rootless by Design

Seven years ago (2018~2019), the idea of “rootless containers” was experimental. Today, it’s the gold standard.

Podman allows “normal” users to run containers without needing to grant yourself rights to specific users,groups or to run as root with sudo or su. It leverages User Namespaces to map a non-privileged user on the host to a “root” user inside the container.

Benefits:

  1. Security: If a process escapes the container, it still only has the permissions of your local user on the host. It cannot touch /etc/shadow or format your disk.
  2. Native SELinux Integration: Podman works out-of-the-box with SELinux, providing labels that prevent containers from peeking into each other’s data or the host’s files.
  3. Lower Resource Footprint: No background daemon means lower idle memory and a smaller binary size.

Podman + Systemd: The DevOps Secret Weapon

This is where Podman truly shines for the Linux purist. Because Podman doesn’t have a daemon, it relies on the OS’s native manager: systemd.

Instead of relying on Docker’s internal --restart always policy, you can treat a container like any other system service.

Generating a systemd configuration which you WILL Be able to run as a user is easy just run podman generate systemd

For rootless containers, these will be stored under the user’s directory: $HOME/.config/containers/systemd/

systemctl --user daemon-reload

To see the status of the container with systemd as a user systemct --user status myapp.service

This means you can use restart/start/stop with systemctl;) THe neat thing is you can run podman without requiring root, thus if you have a multi user environment each user may have his/her own containers. Greatly simplifying even continous integration continous deployment/delivery.

Quadlets: The Modern Way

Podman introduced Quadlets, which allow you to define a container in a simple .container file. Systemd then automatically generates a service for it. As of 2022 this has been integrated in to podman itself.

  • User-Level Services: You can run containers as a user (systemctl --user start my-app).
  • Journald Logs: Container logs aren’t hidden in some obscure Docker JSON file. They are piped directly into journald. You can use journalctl --user -u my-app to see what’s happening, just like any other app on your system. This integratin makes sysadmin much easier.

The “Zero-Registry” Workflow

Standard DevOps tutorials tell you that you must have a centralized registry (DockerHub, GHCR, etc.). But what if you’re working on a private network or a “Sovereign” homelab? Running a docker registry just for your system is overkill, there are better ways to achieve this.

You can move images around like standard files using the power of the pipe (|).

Pushing an image over SSH:

podman image save my-app | ssh user@server.com podman image load

Optimized with compression (faster for slow networks):

podman image save my-app | gzip | ssh user@server.com 'gunzip | podman image load'

Pulling an image from a remote server to your local machine:

ssh user@server.com 'podman image save my-app | gzip' | gunzip | podman image load

This bypasses the need for complex registry authentication and storage when you just need to get a build from your Dev VM to your Production VPS.


Performance Comparison

FeatureDockerPodman
ArchitectureClient-Server (Daemon)Fork-Exec (Daemonless)
Root RequirementMandatory (usually)Rootless by default
SecurityLarge attack surfaceTight (User Namespaces + SELinux)
Init IntegrationCustom Restart PoliciesNative Systemd / Quadlets
LoggingCentralized Docker LogsNative Journald (Per-user)
OCI CompliantYesYes

Conclusion: If you need Containers, use podman

For my projects I have 3 different options for running software which I mostly write and deploy in GOlang nowadays due to the self contained binaries.

  1. I usually go the route of using systemd with my binary by dropping privileges.
  2. The next logical choice is systemd-nspawn which we’ll address in a future day.
  3. The 3rd next logical step is podman. It allows us to:
    1. Run the web engine as an unprivileged user.
    2. Manage the lifecycle via systemd Quadlets.
    3. Keep logs clean and accessible via journalctl.
    4. Deploy updates over a simple SSH pipe without managing a private registry.

Podman feels like a tool built by Linux engineers for Linux engineers. It doesn’t try to abstract the OS away; it embraces it.

Next up for day 7 we’ll setup our own Virtual Private Server in the cloud.