Switching from Podman Quadlets to Podman Compose
I switched from Docker to Podman in my homelab back in 2023, and settled on using Quadlets. I’ve been using this system for about three years, but it’s a bit of a hassle to have to convert any and all Docker Compose files into separate Quadlet files.
If you’re starting out with Podman, you might want to go read the blog post linked above, as it does contain some things to help you get started.
Having grown tired of doing that, I decided to revisit Podman Compose - taking the Compose files created by the upstream projects, and running them through podman instead of Docker. My previous trials with Podman Compose weren’t that great, but somehow now things just worked.
While switching over my container stack I came across a few things that I had to change:
SELinux process labeling
For Traefik I had SecurityLabelType=traefik.process configured so that the process would be labeled with the correct SELinux context. To do this with Podman Compose I had to add
1
2
security_opt:
- "label=type:traefik.process"
to the service definition.
User namespace mapping
Some of my containers use namespace mapping to make the original UID available to the container. I came across this blog post which details a lot of the Podman Compose extensions available.
Previously I had
1
PodmanArgs=--uidmap +1000:@1000:1 --gidmap +1000:@1000:1
which could be mapped to
1
2
3
4
x-podman.uidmaps:
- "+1000:@1000:1"
x-podman.gidmaps:
- "+1000:@1000:1"
in my compose.yml file.
Starting containers automatically at boot
When using Quadlets, systemd will make sure your containers are started at boot. When using Podman Compose, there’s a service you can activate called podman-restart.service to basically do the same thing.
To enable it, run (as your Podman user):
1
systemctl --user enable --now podman-restart.service
If you check out /usr/lib/systemd/system/podman-restart.service, you’ll see that the start command reads
1
ExecStart=/usr/bin/podman $LOGGING start --all --filter should-start-on-boot=true
The man page for podman-start tells us that the should-start-on-boot filter will instruct Podman to start containers with a restart policy of always or unless-stopped.
Automatic updating of containers
Quadlets also offer the feature of updating your containers automatically and restarting them when a new image is available.
In this blog post I found a nifty way to solve this problem:
I created the systemd timer ~/.config/systemd/user/podman-update@.timer:
1
2
3
4
5
6
7
8
9
10
[Unit]
Description=Podman update timer for %i
[Timer]
OnCalendar=daily
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target
and the systemd service ~/.config/systemd/user/podman-update@.service:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Podman auto-update service for %i
Wants=network-online.target
After=network-online.target
[Service]
WorkingDirectory=%h/containers/%i
Environment="DOCKER_HOST=unix:%t/podman/podman.sock"
Type=oneshot
ExecStart=/usr/bin/podman compose pull
ExecStartPost=/usr/bin/podman compose up -d
ExecStartPost=/usr/bin/podman image prune -f
[Install]
WantedBy=default.target
and enabling the timer (per Podman Compose project directory)
1
systemctl --user enable --now podman-update@<directory>.timer
Don’t forget to update the
WorkingDirectoryinpodman-update@.serviceto wherever you store your Podman Compose YAML files! I use~/containers, with a subdirectory per project.
Now my containers get automatically updated and cleanly restarted too.