Introduction
Docker Compose has been a regular way of distributing/running container stacks to deploy services for many years now. What is actually interesting is the “Compose spec”, which mainly defines static representation(s) (it used to be multiple versions of it) of these stacks (i.e. how different services share resources [or not], and “work” together).
For this second post of this “Podman series” (also see “Podman rootless in Podman rootless, the Debian way”), I will explain how I replaced Docker-Compose (and hence Docker itself) by Podman-Compose for some personal services.
From Docker-Compose to Docker Compose
Historically, Composing with Docker was achieved by using Docker-Compose (v1), a binary which was actually a Python program built using PyInstaller, and invoked by docker-compose
. On Debian, it is still packaged in main repositories.
Since 2021 (and mostly since last year), Composing is now achieved using Docker Compose (v2), a Go plugin for the docker
(client) CLI.
On Debian, once Docker repository has been added, setup is pretty straightforward : apt install docker-ce docker-compose-plugin
.
Invocation is then done by docker compose
(please note the space instead of the dash).
In either case, a docker-compose.yml
file is usually downloaded according to vendor recommendations (or carefully handcrafted when missing ), and modulo a docker[-]compose up -d
invocation, you’re all set and running.
Composing with Podman
Whereas Podman has been built as a “drop-in replacement” for Docker (despite internals being fundamentally different), Composing was initially out-of-scope (or very partially supported). But it’s 2023, and Podman-Compose is now a robust alternative.
Within this containers ecosystem where (almost) everything is written in Go, please welcome Python again (and mind the coming back of the dash !).
Podman-Compose implements the Compose spec, while still being oriented “rootless” (after all, it’s what we expect from Podman, isn’t it ?) and “daemon-less”.
Podman-Compose setup for Debian 12 (Bookworm)
First we create a system user dedicated to Podman execution :
Unlike Docker, there is no such thing as a (privileged) daemon running and waiting for us to give commands.
So we must enable systemd-logind “lingering” for our system user to make systemd start (in user mode) on machine boot, and thus provide a proper runtime for OOTB Podman execution :
Now we can install Podman and deal with Debian (undesired) pulled dependencies :
We then define our ranges of UIDs/GIDs dedicated to our system user :
Podman-Compose is packaged in Debian main repositories, but (already) pretty old so you’ll understand why we go through PyPI to retrieve an up-to-date version.
As we like doing clean things and we actually don’t wanna break our system, we will install podman-compose
in a Python virtual environment :
Now we can finalize the setup as our regular system user :
The restart
policy pitfall
Sooo, as you may already know, containers do not start on boot by default. This behavior depends on the --restart={always,no,on-failure[:max-retries],unless-stopped}
flag, that you can should specify when creating a container (or through the restart
key in a Compose file).
Unlike for “standalone” Podman where we could run podman generate systemd <container>
to make a container actually managed by systemd as a regular “service” (and thus enjoy the Restart
policy feature), there is no such thing (yet ?).
As a workaround, we can rely on the (global) systemd service unit (called podman-restart.service
), responsible for restarting containers on boot, that we must enable in our (user mode) systemd runtime :
Whereas unless-stopped
is supposed to be identical to always
with Podman, packaging hits us hard and that’s unfortunate.
podman-restart.service
unit specifies --filter=always
to only (re)start containers that should be.
So you must add :
… to your Compose stacks to enjoy containers auto-restart, or you will have to tweak the upstream systemd unit
This issue has already been mentioned two years ago by @plevart, but it has not been fixed yet.