Docker vs Podman

Posted on May 20, 2024 by Brian Jaress
Tags: code, review

I recently switched from Docker to Podman for personal use, and it’s been relatively painless.

Major Differences

There were really only two changes to make.

One was setting the user namespace1 with --userns=keepid in cases where I was already setting the user with --user=$(id -u):$(id -g).

The other change was adding to FROM instructions, making them fully qualified when pulling base images from Docker Hub.2 For example, FROM swipl:stable became FROM This change wasn’t strictly necessary. Podman can also be configured to search whenever the instruction is not fully qualified. On some systems, Podman might even be installed with that configuration by default.3

What I Use It For

I have justified things by mentioning personal use, so I should explain what I use it for. It’s mainly not the typical use case for containers, where the emphasis is on portability and consistency when managing processes at scale.4

I tend to write Bash scripts that use other command-line applications. Many of them are mixtures of existing applications and custom code, and the dependency on those existing applications used to be managed separately from whether they were installed on the system. They also turned my system into a dumping ground for applications used by one or two scripts.

With containers, I can automatically pull entire applications into the container image when it’s built and keep them inside the container. (Similar to how library dependencies are handled in mainstream programming languages.) That may seem like a small thing, but it’s incredibly freeing.

A recent example is a script I wrote that generates snippets of sheet music and accompanying audio from YAML files. It uses Python to read the YAML and generate files for LilyPond, which generates SVG images and MIDI files. Then TiMidity++ generates Ogg audio files from the MIDI.

If your browser supports Ogg Vorbis audio and SVG images, here’s a bit of the output:

A snippet of sheet music

A clunkier example is my news feed generator, which uses a hodgepodge of RSS, web scraping, and formatting utilities, then spits out an EPUB.

Something slightly different is a collection of Dockerfiles, with a single script choosing which one to build and run, that I use for launching REPLs. There was a period where it seemed to be getting a lot easier to find online read-eval-print loops for a variety of languages, but now it seems to be getting a little bit harder again. With that script and its associated files, I can type repl scheme to get Scheme, repl prolog to get Prolog, and so on for a collection of languages.

Why I Switched

The reason I switched wasn’t any kind of major problem. Docker has been great! I just wanted to try Podman.

Some of the design decisions do feel a little more appropriate. For example, there is no daemon running all the time, and it’s rootless by default. But if it were a serious inconvenience to switch, I wouldn’t have bothered.

So far, I’m glad I did.

  1. There’s a lot more to know about user mapping, but that’s been enough for my personal use cases.↩︎

  2. It is a little counter-intuitive to add as part of a move from Docker to Podman, but it’s a case of explicitly stating something that used to be a default. I am still using Docker Hub as a registry.↩︎

  3. On my system, the default install doesn’t have that configuration. In fact, it has a warning from the creators of Podman about how dangerous it would be to do that. The reason given seems like it would apply to Docker as well, even though many people use Docker that way, so it’s very tempting to just ignore that warning. On one hand, if is the only registry you implicitly search (because every place your container image gets built is configured that way) a FROM instruction with no host should do the same thing as a FROM instruction with On the other hand, adding isn’t that hard and leaves less to chance.↩︎

  4. I also do that – building a container image with a single application inside it, pushing it into a registry, and then running it elsewhere – but that’s more of a work use-case than a personal one.↩︎