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:
- Use case
- Requirements
- Environment and container image used
- Configuration of the
systemd
service with auto-update function - 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.
Requirements
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.
- Podman Installation Instructions
- Basic Setup and Use of Podman in a Rootless environment
- Quick Tip: Rootless Podman + docker-compose on Fedora
- RHEL 9: Setting up rootless containers
- RHEL 8: Setting up rootless containers
You should also be able to read man pages.
Environment and container image used
- RHEL 9
- Podman 4.4.1
- Container image by louislam/uptime-kuma
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
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 docker.io/louislam/uptime-kuma:latest
Trying to pull docker.io/louislam/uptime-kuma:latest...
Getting image source signatures
…
Writing manifest to image destination
Storing signatures
ad7b049d9b84962311f5bafb5329f59961d8a031e54a571f079b8243ea8059ee
Code 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
docker.io/louslam/uptime-kuma:latest
. - 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
[Unit]
Description=Podman container-uptime-kuma.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
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 \
--name=uptime-kuma docker.io/louislam/uptime-kuma:latest
ExecStop=/usr/bin/podman stop \
--ignore -t 10 \
--cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm \
-f \
--ignore -t 10 \
--cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all
[Install]
WantedBy=default.target
Code 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.service
Code 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}}"
docker.io/louislam/uptime-kuma:latest false
Code 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) docker.io/louislam/uptime-kuma:latest registry false
Code 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/default.target.wants/podman-auto-update.service → /usr/lib/systemd/user/podman-auto-update.service.
Created symlink /home/tronde/.config/systemd/user/timers.target.wants/podman-auto-update.timer → /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 https://www.my-it-brain.de/wordpress/container-mit-podman-auto-update-automatisch-aktualisieren/