Automatically update containers with podman-auto-update

September 4, 2023

Photo by Timelab on Unsplash

In this tutorial I will show you how to configure automatic updates for containers in rootless Podman environments and how systemd manages these containers as services.

The tutorial is divided into the following sections:

  1. Use case
  2. Requirements
  3. Environment and container image used
  4. Configuration of the systemd service with auto-update function
  5. Update containers (automatically)

If you are not interested in the possible use cases and would rather start right away, you can skip the first section. The remaining sections should be read in the order presented.

Use Case

  • Containers run on a single container host and not in K8s environments.
  • The provider is trusted to provide stable and usable container images.
  • It should be checked regularly whether updated container images are available.
  • If more recent images exist, running containers should be removed and rebuilt using the latest image.


To follow this tutorial you need a host with a rootless Podman environment. Podman must be available in version >= 3.3. In the following list you will find some links that will help you to set up such an environment.

You should also be able to read man pages.

Environment and container image used

The operating system plays a secondary role because we are decoupling the application from the operating system through the use of containers. All the dependencies necessary for the application to run are part of the container image.

Uptime Kuma is a lean and fast monitoring application, which is provided as a container image. I have chosen this application as an example for this tutorial because I would like to use the application myself, and thus be able to take advantage of the synergy effects.

If you want to use a different container image, you must replace  louislam/uptime-kuma:latest with the fully qualified container name of the image to be used in the following examples.

The Podman man pages available on the system are used for configuration.

Configuration of the systemd service with auto-update function

The following steps are based on the example from podman-auto-update(1). I first show the command to be executed in a code block, followed by an explanation of the options used.

Create Podman volume

$ podman volume create uptime-kuma

In order to be able to store data persistently, it must be stored outside the container. The command shown creates a Podman volume named uptime-kuma.

The following command displays detailed information about the volume just created:

$ podman volume inspect uptime-kuma
          "Name": "uptime-kuma",
          "Driver": "local",
          "Mountpoint": "/home/tronde/.local/share/containers/storage/volumes/uptime-kuma/_data",
          "CreatedAt": "2023-08-22T20:52:06.477341481+02:00",
          "Labels": {},
          "Scope": "local",
          "Options": {},
          "MountCount": 0,
          "NeedsCopyUp": true,
          "NeedsChown": true
]Code language: JavaScript (javascript)

The key Mountpoint contains the path on the local file system where the volume was created.

Related man pages:

Start containers

$ podman run --label "io.containers.autoupdate=registry" -d -p 3001:3001 -v uptime-kuma:/app/data:Z --name=uptime-kuma
Trying to pull
Getting image source signatures
Writing manifest to image destination
Storing signatures
ad7b049d9b84962311f5bafb5329f59961d8a031e54a571f079b8243ea8059eeCode language: JavaScript (javascript)
  • podman run is the command used to start a new container.
  • The option --label "io.containers.autoupdate=registry" specifies that Podman will check the remote registry for an updated image; this label is required to be able to use the auto-update feature.
  • With the option, -d the container is started detached and the container ID is printed to STDOUT.
  • Option -p 3001:3001 connects the host port 3001 to the application’s port (also 3001) in the container.
  • The option -v uptime-kuma:/app/data:Z mounts the Podman volume created in the previous step to the directory /app/data inside the container; :Z ensures that the SELinux context is set correctly.
  • --name=uptime-kuma specifies the name of the container; this is slightly easier to remember than the container ID.
  • The command ends with the fully qualified container name
  • The last line of the code block contains the container ID.

Man pages:

Create systemd service unit with podman-generate-systemd

$ podman generate systemd --name --new uptime-kuma
# container-uptime-kuma.service
# autogenerated by Podman 4.4.1
# Tue Aug 22 21:29:46 CEST 2023

Description=Podman container-uptime-kuma.service

ExecStart=/usr/bin/podman run \
	--cidfile=%t/%n.ctr-id \
	--cgroups=no-conmon \
	--rm \
	--sdnotify=conmon \
	--replace \
	--label io.containers.autoupdate=registry \
	-d \
	-p 3001:3001 \
	-v uptime-kuma:/app/data:Z \
ExecStop=/usr/bin/podman stop \
	--ignore -t 10 \
ExecStopPost=/usr/bin/podman rm \
	-f \
	--ignore -t 10 \

WantedBy=default.targetCode language: PHP (php)
  • The command outputs the content of the generated service unit to STDOUT.
  • The option --name uses the name of the container instead of the container ID in the file name of the service unit (here: container-uptime-kuma.service).
  • The option --new is important in order to be able to create containers from updated images; without this option, systemd units can only start and stop containers using the original image and auto-update is not possible.
  • The following code block adds the option --files to the command to create a service unit file.
$ podman generate systemd --name --new --files uptime-kuma
/home/tronde/container-uptime-kuma.serviceCode language: JavaScript (javascript)

Man pages:

Activate and start the created systemd unit

$ systemctl --user status container-uptime-kuma.service
○ container-uptime-kuma.service - Podman container-uptime-kuma.service
     Loaded: loaded (/home/tronde/.config/systemd/user/container-uptime-kuma>
     Active: inactive (dead)
       Docs: man:podman-generate-systemd(1)
$ podman stop uptime-kumauptime-kuma
$ podman rm uptime-kumauptime-kuma
$ systemctl --user start container-uptime-kuma.service
$ systemctl --user status container-uptime-kuma.service
● container-uptime-kuma.service - Podman container-uptime-kuma.service
     Loaded: loaded (/home/tronde/.config/systemd/user/container-uptime-kuma>
     Active: active (running) since Tue 2023-08-22 21:59:56 CEST; 14s ago
…Code language: JavaScript (javascript)
  • The first command in the code block above checks the current status of the service.
  • The second and third command stop and remove the running container that we started earlier.
  • Command number 4 starts the Uptime Kuma service.
  • Command number 5 checks the new status of the service; this is now up-and-running.

Man pages:

Check for new container images

$ podman auto-update --dry-run --format "{{.Image}} {{.Updated}}" falseCode language: JavaScript (javascript)
  • The option --dry-run ensures that new images are checked for availability, but no pull operations are performed and no containers are rebuilt.
  • A list of container images launched with the label io.containers.autoupdate=registry is printed to STDOUT.
  • The first column contains the image name.
  • The second column shows if an update is available; in this case no update is available (false).

Update containers (automatically)

If the configuration was successfully completed, the corresponding containers can be updated manually with the following command:

$ podman auto-update
UNIT                           CONTAINER                   IMAGE                                  POLICY      UPDATED
container-uptime-kuma.service  df21116f2573 (uptime-kuma)  registry    falseCode language: JavaScript (javascript)

Unfortunately, no update is currently available, which is why there is nothing to do here.

Podman ships the two systemd units podman-auto-update.timer and podman-auto-update.service, which must be activated manually at least under RHEL 9:

$ systemctl --user enable podman-auto-update.{service,timer}
Created symlink /home/tronde/.config/systemd/user/ → /usr/lib/systemd/user/podman-auto-update.service.
Created symlink /home/tronde/.config/systemd/user/ → /usr/lib/systemd/user/podman-auto-update.timer.

$ systemctl --user start podman-auto-update.timer
$ systemctl --user status podman-auto-update.{service,timer}
○ podman-auto-update.service - Podman auto-update service
     Loaded: loaded (/usr/lib/systemd/user/podman-auto-update.service; enabled; preset: disabled)
     Active: inactive (dead)
TriggeredBy: ● podman-auto-update.timer
       Docs: man:podman-auto-update(1)

● podman-auto-update.timer - Podman auto-update timer
     Loaded: loaded (/usr/lib/systemd/user/podman-auto-update.timer; enabled; preset: disabled)
     Active: active (waiting) since Sat 2023-09-02 20:56:09 CEST; 1s ago
      Until: Sat 2023-09-02 20:56:09 CEST; 1s ago
    Trigger: Sun 2023-09-03 00:12:22 CEST; 3h 16min left
   Triggers: ● podman-auto-update.service

Sep 02 20:56:09 podhost-p1.lan systemd[686]: Started Podman auto-update timer.Code language: JavaScript (javascript)
  • The timer starts the auto-update service at midnight every day.
  • The service checks whether updated container images are available and, if necessary, updates the containers.
  • If a startup fails after updating the container image, the service will automatically start from the previous image version; see --rollback in podman-auto-update(1).
  • By the way, the podman auto-update feature is also supported for workloads defined by means of Kubernetes YAML. For more information on this, see How to run Kubernetes workloads in systemd with Podman and the section “Auto Updates and Kubernetes YAML” of podman-auto-update(1).

I hope you enjoyed the tutorial and that it has given you an idea of ​​how to configure automatic updates for containers.

A German version of this article was first published at

Leave a Reply


Subscribe to our newsletter.

Please select all the ways you would like to hear from Open Sourcerers:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our newsletter platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.