Podman Quadlet vs podman run vs podman-compose: a host service decision
Decision guide for choosing Podman Quadlet over imperative podman run or podman-compose for long-running, systemd-managed containers on Linux hosts, with constraints, trade-offs and a concrete Quadlet example with validation steps.
10 Oct 2026, 03:15 UTC

The problem is durability, not launching
You need a container to survive reboots, restart on failure, start after network or storage, and log to the host journal without a separate supervisor. podman run starts a container. podman-compose starts a set of containers. Neither gives you first-class systemd integration on a Linux host.
Use Quadlet .container and .pod files when the requirement is host-integrated, auto-restarting services with systemd ordering, journal logging, and no external orchestrator. The constraints are a systemd-based Linux host, Podman 4.0+ with Quadlet enabled, and acceptance of unit files in ~/.config/containers/systemd for user services or /etc/containers/systemd for system services.
Decision constraints
Quadlet is declarative. You write a .container or .pod file, Podman generates a systemd unit, and systemd owns lifecycle. This works rootless with user units and as root with system units.
Prerequisites to check before committing:
- Host uses systemd as init.
- podman --version reports 4.0 or newer and podman quadlet --help is available.
- For rootless: user subuid/subgid mappings are configured and cgroup v2 is active. Without cgroup v2, restart and resource limits may fail silently.
- For system units: you have root access and understand SELinux/AppArmor contexts for the container.
Options compared
| Option | Management model | Restart / ordering | Logging | Portability |
|---|---|---|---|---|
| Quadlet .container | Declarative systemd unit generated from file | systemd Restart=, After=, Requires= | journald via systemd | Host specific |
| podman run script | Imperative CLI, cron or rc.local | Manual, no native ordering | container stdout | Portable |
| podman-compose | Compose YAML translated to pods/containers | Depends on compose process supervisor | stdout files | Compose portable |
Trade-offs
Quadlet gives first-class systemd integration, automatic restarts on failure or reboot, and centralized logging. The cost is host coupling and learning unit file semantics. Unit files live on the host, so moving the workload requires copying files and host configuration.
podman run is simplest for ad-hoc tasks and one-off jobs. It lacks durability, dependency handling, and boot ordering. It is portable but operationally fragile.
podman-compose preserves compose familiarity and multi-service definitions. It adds a runtime dependency and does not map cleanly to systemd units, complicating host boot ordering and user session restarts.
Concrete implementation for a user service
Create a user Quadlet file. The directory is ~/.config/containers/systemd. The filename webapp.container defines the unit name webapp.service.
[Unit]
Description=Webapp
[Container]
Image=docker.io/library/nginx:latest
AutoUpdate=registry
PublishPort=8080:80
Run the commands as the target user on the host terminal. No root is required for user units.
podman quadlet --user --dry-run
podman quadlet --user install
systemctl --user enable --now webapp.service
podman quadlet --user install generates the systemd unit files in the user systemd directory. enable --now creates the symlink and starts the service. Risk: mixing user and system directories can create duplicate units. Keep user definitions under ~/.config/containers/systemd and system definitions under /etc/containers/systemd.
Validation
Check unit state and container state separately.
systemctl --user is-enabled webapp.service
systemctl --user status webapp.service
podman ps --filter label=io.containers.autoupdate
journalctl --user -u webapp.service
Expected checks: systemctl reports enabled and active, podman ps shows a container with the published port, and journalctl shows systemd events and container stdout. podman inspect can confirm labels, ports and restart policy.
Rollback if needed: stop and remove the generated units.
systemctl --user disable --now webapp.service
podman quadlet --user uninstall
Limitations and version sensitivity
Quadlet file keys and AutoUpdate semantics changed across Podman 4.x to 5.x. Verify your Podman version before relying on specific keys.
Rootless Quadlet requires correct user namespace mappings and cgroup v2 for full functionality. Without them restart and resource limits may fail silently.
System Quadlet files run as root and need careful SELinux/AppArmor contexts. Image updates via AutoUpdate=registry are pull-based and depend on Podman version and registry authentication configured in containers.conf.
Use Quadlet when the service belongs to the host lifecycle. Use podman-compose for portable multi-service development stacks, and podman run for ephemeral tasks.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.