
Manage Podman containers with Systemd and Quadlet
May 17, 2023
Until a few months ago, the only option to start containers from Systemd was to create a Systemd unit which called podman
(or docker
) with the run
sub-command.
Podman was also providing podman generate systemd
to easily create such Systemd file.
This has now changed. From version 4.4 of Podman, in addition to the mentioned method, it is possible to use Quadlet to simplify the execution of containers from Systemd.
Quadlet allows you to create additional kinds of Systemd units to manage your container needs:
- container
- volume
- network
- kube
These new resources are used to manage the corresponding Podman resources.
Systemd does not directly read Quadlet units and, therefore, they will need to be placed in different folders, and more specifically in:
/etc/containers/systemd/
(system units)/usr/share/containers/systemd/
(system units)$XDG_CONFIG_HOME/containers/systemd/
(user units)~/.config/containers/systemd/
(user units)/etc/containers/systemd/users/$(UID)
(user units)/etc/containers/systemd/users/
(user units)
Creating a container unit is very simple, and a minimal one for HAProxy looks like this:
[Unit]
Description=HAProxy
After=local-fs.target
[Container]
ContainerName=haproxy
Image=docker.io/library/haproxy:2.7.8
Volume=/opt/haproxy:/usr/local/etc/haproxy:z
PublishPort=8080
To create the Systemd unit in the filesystem, we will simply reload the Systemd units with systemctl daemon-reload
.
We can now proceed with starting or enabling it as we would for any other Systemd unit.
Suppose you are curious to see what Systemd unit got created by Quadlet.
In that case, you can run /usr/libexec/podman/quadlet -dryrun
, which will dump the automatically generated Systemd unit to your console.
Quadlet works by creating the native Systemd resources dynamically at every boot or every time the Systemd units are reloaded via the systemctl daemon-reload
command.
An aspect I really like about Quadlet’s approach is that the units created in this way are fully integrated in Systemd.
Let’s say we want to execute the hello
job at the fifth minute of every hour.
First, we will create the container unit in /etc/containers/system/hello.container
with the following content:
[Unit]
Description=Hello
After=local-fs.target
[Container]
ContainerName=hello
Image=quay.io/podman/hello:latest
We can now create a timer unit in /etc/systemd/system/hello.timer
with the following content:
[Unit]
Description=Hello
[Timer]
OnCalendar=*-*-* *:05:00
[Install]
WantedBy=timers.target
We are now ready to reload the Systemd units (systemctl daemon-reload
) and start the timer with systemctl start hello.timer
.
The hello task will then be executed every hour until the machine is turned off.
To keep the timer working after a reboot, you’ll also need to enable the timer with systemctl enable hello.timer
.
I really like this new feature of Podman since it allows me to simplify the execution of containers for services as well as for batch jobs. Also, being very well integrated with all other Systemd logic, it can already solve a lot of different use cases, even though the feature is very new.