It is a good practice to update software, especially when you get new features and/or added security in the new updates.
In this article, I will show you how to enable automatic updates for the containers managed by Podman.
For demonstration purposes, I will use the
caddy image from Docker Hub.
Determine the source for fetching image
To use a container image, Podman needs to pull that image from somewhere. This "somewhere" is referred to as the auto-update policy.
The auto-update policies are as following:
registry: When the auto-update policy is set to the string
registry, Podman will pull the image from a remote registry like Docker Hub and Quay.io.
local: When the auto-update policy is set to the string
local, Podman will fetch image from locally built images. This update policy comes in handy when you are a developer and wish to test local changes before pushing them to a remote registry.
Simply use the
sudowhen you encounter an error related to privileges (only if you have a root-full container).
Now that you are aware of what an "auto-update policy" is, we can now proceed with this tutorial.
All that you need to do to enable automatic updates for a container managed by Podman is to add the following label:
Substitute the string
AUTO_UPDATE_POLICY with either
registry or with
local and you're good to go!
"But how will the container auto-update when Podman does not have a daemon?"
When I said that "You only need to add the
io.containers.autoupdate label to your container," you see... I
The container that needs to be automatically updated must be managed by systemd. "Why are you shoving systemd down my throat?" Well because Podman has a daemon-less architecture. And the container needs to be managed somehow.
If you want your container to be started automatically on boot, you already are using systemd to do so.
In the article linked below, I discuss how you can integrate a Podman container--be it a root-full container or a root-less container--with systemd (with the intention of auto-starting it on boot as well).
Regardless, I will give you a quick overview of how to manage Podman containers using systemd.
Step 0: Create a container
Make sure that you have an existing container. It does not matter if the container is running or stopped.
You can check what containers you have by running the following command:
podman container list
For this tutorial, I have pulled an older image of Caddy Server (version
2.5.2-alpine) and have renamed it to
alpine. Renaming this image will help demonstrate the update process. You can check it yourself because the image ID of tag
alpine are same ;)
Using this image, I created a container that is named
Below is how it looks on my computer:
$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/library/caddy 2.5.2-alpine d83af79bf9e2 2 weeks ago 45.5 MB docker.io/library/caddy alpine d83af79bf9e2 2 weeks ago 45.5 MB $ podman container list CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 99d1838dd999 localhost/caddy:alpine caddy run --confi... 5 seconds ago Up 6 seconds ago prathams-caddy
As you can see, I have a container called
prathams-caddy and it is running the
caddy image (which is at an older version).
prathams-caddy was created with the label
io.containers.autoupdate set to
registry. If you have an existing container without this label, do not worry; you don't need to re-create your container. This will be covered in the next step.
Step 1: Generate a systemd service file for your container
Well, to manage your Podman container via systemd, it needs to be turned into a service. Realistically speaking, you want your container to start at boot and want to stop it when you turn off the system. It makes sense to run your container as a systemd service.
"But isn't it a too much work to write a systemd service file for each container I have?" It is. And developers of Podman have thought of this. The only manual work you need to to do is run a command for each of your containers.
If you have a root-full container (a container with root privileges), run the following command:
sudo podman generate systemd -f --new --name CONTAINER_NAME
If your container is a root-less container (a container without root privileges), run the following command:
podman generate systemd -f --new --name CONTAINER_NAME
Substitute the string
CONTAINER_NAME with the name of your container and a file with the name
container-CONTAINER_NAME.service will be created.
For my Caddy Server container, I will do the following:
$ podman generate systemd -f --new --name prathams-caddy /home/pratham/container-prathams-caddy.service
As evident from the output, the file
container-prathams-caddy.service was created. It will be created in the current working directory.
But this is for containers that already have a value set for the label
io.containers.autoupdate. What about containers that already exist without this label? You don't have to re-create your containers with this label.
In that case, edit the systemd service file and add the following line to the
ExecStart field like so:
[...] ExecStart=/usr/bin/podman run \ [...] --label io.containers.autoupdate=registry [...]
Essentially, your systemd service file is just invoking the
podman run command. All you are doing is adding the label
io.containers.autoupdate to the
podman run command. Neat?
Step 2: Move the systemd service file
Now that a systemd service is already created for us, we need to enable it. But before it is enabled, the service file needs to be moved in one of the following directories:
/etc/systemd/system/: If the container is root-full and needs to be started with superuser privileges.
~/.config/systemd/user/: If the container is root-less, place it in the corresponding directory of the user that is intended to start it.
prathams-caddy is a root-less container so I will move it accordingly.
$ mv -v container-prathams-caddy.service ~/.config/systemd/user/ renamed 'container-prathams-caddy.service' -> '/home/pratham/.config/systemd/user/container-prathams-caddy.service'
Step 3: Enable the systemd service
Now that the service file is placed in an appropriate directory, we can proceed to enable it. But first, systemd needs to be made aware of our newly created service without rebooting our computer.
If the service needs superuser privileges, reload systemd using the following command:
sudo systemctl daemon-reload
If the service is starting a root-less container, run the following command:
systemctl --user daemon-reload
Once that is done, we can simply use the
systemctl enable command to enable our service. Use either command based on your requirements:
# for a root-full container sudo systemctl enable SERVICE_NAME.service # for a root-less container systemctl --user enable SERVICE_NAME.service
Once enabled, you can check the status of your service. Do not be alarmed if it says
inactive (dead). This is because our service starts at boot and we haven't booted up the computer after enabling the service.
$ systemctl --user enable container-prathams-caddy.service Created symlink /home/pratham/.config/systemd/user/default.target.wants/container-prathams-caddy.service → /home/pratham/.config/systemd/user/container-prathams-caddy.service. $ systemctl --user status container-prathams-caddy.service ○ container-prathams-caddy.service - Podman container-prathams-caddy.service Loaded: loaded (/home/pratham/.config/systemd/user/container-prathams-caddy.service; enabled; vendor preset: enabled) Active: inactive (dead) Docs: man:podman-generate-systemd(1)
Now is the best time to stop the container (if it is running) and
podman container rm it and reboot.
$ podman stop prathams-caddy prathams-caddy $ podman container rm prathams-caddy 99d1838dd9990b2f79b4f2c83bc9bc16dfbaf3fdeeb6c6418ddd6e641535ce21
Step 4 (optional): Enable user lingering
If you created a systemd service for a root-less container, it is best to enable user lingering for your particular user.
This can be achieved by running the following command:
sudo loginctl enable-linger
So will my container auto-update now?
"I added the
io.containers.autoupdate label to my container(s). I also manage my container(s) with systemd now. Will my container automatically update the image now?"
Well no... But only one step remains... that ought to count for something, right? Right? right...?
All that needs to be done now is to enable the
podman-auto-update service. Do so with the following command:
sudo systemctl enable podman-auto-update.service
podman-auto-update service enabled, systemd will check if any image needs to be updated. If there are updates, the images if fetched first. Then the container is restarted. The old image is kept in case the update needs to be rolled back for n number of reasons.
Auto updates? No thank you.
If auto-updates are not your thing, you may also be pleased to know that you can manually update containers with just one command, provided they are managed by systemd.
That command is the
podman auto-update command. And if you just want to check for updates, pass in the
--dry-run option so that no containers are actually upgraded.
Let's check if I can upgrade my
caddy image from '2.5.2-alpine' to '2.6.1-alpine' using the
podman auto-update command.
$ podman container list CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a712a3c8846b docker.io/library/caddy:alpine caddy run --confi... 2 seconds ago Up 2 seconds ago prathams-caddy $ podman auto-update --dry-run UNIT CONTAINER IMAGE POLICY UPDATED container-prathams-caddy.service a712a3c8846b (prathams-caddy) caddy:alpine registry pending
As you can see in the
UPDATED column of the output of
podman auto-update command, it says
pending. This indicates that an update is available.
To update the container, remove the
The process of enabling automatic updates for your Podman containers can feel a bit involving, but trust me, this will pay off in the long run. All of your containers that are managed will be automatically updated at midnight (if there are any updates). And, if the container faces any problems, systemd will roll it back to an older image, so your container keeps on running.
If you found this useful, please comment down below and tell us your thoughts! <3