Learn Podman - Advanced Systemd & Service Lifecycle
Series/Learn Podman/Episode 17
Episode 17 of 23

Learn Podman - Advanced Systemd & Service Lifecycle

Managing the container lifecycle as advanced systemd services: socket activation for on-demand services via socket units, image auto-update with podman auto-update, Quadlet unit generation, and safe update and rollback strategies.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

In episode 16 you hardened containers with resource limits, read-only rootfs, and auditing. Now comes the peak of the systemd phase: how to make containers behave like production services — starting only when needed, updating themselves when a new image is available, and rolling back to an old version in seconds. Episode 17 brings together Quadlet, socket activation, and podman auto-update.

Recap: Quadlet from Episode 10

In episode 10 you learned about Quadlet: .container, .pod, .volume, and .image systemd units that are automatically translated into regular systemd units. Its advantage is now clear: these units can leverage all of systemd's features, including dependencies, restart policies, and the socket activation you're about to see.

Socket Activation: On-Demand Services

Socket activation lets a service only start when a connection arrives. systemd holds the socket first; when a request comes in, systemd launches the container. The result: the container doesn't consume resources while idle.

The manual way, with a socket unit:

Linuxapp.socket - the always-listening socket
[Unit]
Description=Socket untuk app container
 
[Socket]
ListenStream=8080
SocketMode=0660
 
[Install]
WantedBy=sockets.target

And on the Quadlet side, the .container unit is paired with a .socket file with the same name. Quadlet recognizes this pair and connects them automatically:

Linuxapp.container - the socket-activated container
[Unit]
Description=App container on-demand
 
[Container]
Image=quay.io/example/app:1.2
PublishPort=127.0.0.1:8080:8080
 
[Service]
Restart=on-failure
 
[Install]
WantedBy=default.target

Enable the pair:

Enabling socket activation
systemctl --user daemon-reload
systemctl --user enable --now app.socket
systemctl --user status app.socket

As long as there's no connection to port 8080, the container doesn't run — saving memory and CPU. As soon as a request arrives, systemd starts the container within seconds.

podman auto-update

One of the biggest operational challenges: ensuring containers use the latest image without manual work. podman auto-update solves it. Containers you want updated are marked with a label:

LinuxMarking a container for auto-update
[Container]
Image=docker.io/library/nginx:1.26
Label=io.containers.autoupdate=registry

Then run the update:

Checking and running auto-update
podman auto-update --dry-run
podman auto-update

podman auto-update --dry-run shows which containers have a new image version without changing anything; without --dry-run it pulls the new image and restarts the container. For locally built containers, use io.containers.autoupdate=local.

Important

Auto-update replaces the image a unit references, but the restart policy stays with that unit. Make sure Restart=always or on-failure is set in the Quadlet [Service] section, and test --dry-run on staging first before letting it run in production.

Podman Systemd Generators

Writing Quadlet from scratch can be tedious for already-running containers. Podman provides a generator to reverse the process: from an active container or pod to a Quadlet unit file:

Generating a Quadlet unit from a running container
podman systemd generate --name myapp --files
ls -la ~/.config/containers/systemd/

podman systemd generate --files writes .container or .pod files ready to copy into the Quadlet directory. For a classic systemd unit style, podman generate systemd still exists — but Quadlet is the recommended direction going forward.

Safe Image & Tag Updates

A safe update strategy isn't just pulling the latest image, it's making sure you can go back:

  1. Always pin predictable tags — avoid latest in production; use version tags like 1.2.3.
  2. Pull and test first — pull the new image, run it as a separate instance, test the healthcheck.
  3. Update deliberately — restart the service onto the new image and monitor metrics.
  4. Prepare the rollback — the old image stays in storage; rollback is just changing the unit tag then systemctl --user restart.

Service Lifecycle in Systemd

PhaseToolCommand / action
DefinitionQuadlet .containerWrite the file in the systemd directory
Activationsystemdsystemctl --user enable --now
On-demandSocket activationsystemctl --user start app.socket
Updatepodman auto-updatepodman auto-update
RollbackImage tagChange the tag, restart the unit
Inspectionsystemd + Podmansystemctl --user status, podman logs

The combination of these tools turns a container from an object run once into a service fully managed by systemd.

Closing

In episode 17 you managed the advanced service lifecycle: socket activation with systemd units and Quadlet pairs, automatic updates with podman auto-update, Quadlet unit generation via podman systemd generate, and safe tag-based update and rollback strategies.

The key points to take home:

  • Socket activation starts a container only when needed — resources shrink without losing speed.
  • Auto-update demands the right restart policy — test --dry-run before trusting automation.
  • Quadlet is the format of the future — generate it from running containers with podman systemd generate.
  • Rollback is always prepared — pin tags, keep old images, and don't fear restarts.

In the next episode, Episode 18, we shift from choreography to performance: performance & optimization — how layer caching and multi-stage builds speed up the pipeline, leveraging zstd:chunked partial pulls, and maintaining storage with garbage collection and pruning.

Learn Podman - Advanced Systemd & Service Lifecycle | Learn Podman