Late-night Stories: Why I Stopped Manual Container Updates
It’s 2 AM, and the Telegram bot reports a server crash. I scrambled out of bed to check, only to find that the Nginx image I had casually podman pulled earlier that afternoon had a config error, preventing the container from restarting after a server reboot. Constantly typing manual pull commands is a recipe for disaster.
After two years of using Fedora as a dev machine, I realized that installing third-party tools like Watchtower is unnecessary. Fedora and Podman come with Auto-update built directly into systemd. This solution saves about 20-50MB of RAM compared to running Watchtower. Most importantly, it can immediately Rollback to the previous version if a new update fails.
Quick Start: Configure Auto-update in 5 Minutes
To let Podman identify which containers need updating, you just need to assign a label during initialization. Follow the steps below.
Step 1: Run the Container with an Identifying Label
Note: You must use the fully qualified image name (including the registry) so Podman can check the digest accurately.
podman run -d --name my-web-app \
--label "io.containers.autoupdate=image" \
docker.io/library/nginx:latest
The io.containers.autoupdate=image label acts as a “flag.” It instructs Podman to periodically check for new versions on Docker Hub.
Step 2: Create a systemd File to Manage the Container
Podman operates on a daemonless model, so it requires systemd for lifecycle management. Create the service file using the following command:
mkdir -p ~/.config/systemd/user/
cd ~/.config/systemd/user/
podman generate systemd --name my-web-app --files --new
The --new parameter is mandatory. It allows Podman to create a fresh container from the newly downloaded image instead of trying to restart the outdated one.
Step 3: Enable the Service and Timer
Now it’s time to reload the systemd configuration and enable the service:
systemctl --user daemon-reload
systemctl --user enable --now container-my-web-app.service
To check if everything is ready, you can run a dry-run simulation:
podman auto-update --dry-run --format "{{.Image}} {{.Updated}}"
How It Works: Don’t Just Copy-Paste, Understand It
When the podman auto-update command is triggered, the system performs a 4-step process:
- Scans running containers with the
io.containers.autoupdatelabel. - Sends a request to the Registry (Docker Hub, Quay.io) to fetch the image digest.
- Compares digests. If the version on the Registry is newer, Podman pulls the image.
- Restarts the systemd service to launch the new container from the pulled image.
By default on Fedora, a timer named podman-auto-update.timer runs at 00:00 every day. You can check the schedule using the command:
systemctl --user status podman-auto-update.timer
Rollback Pro-tip: Insurance for a Good Night’s Sleep
The best part about Podman is its self-healing capability. Often, a newly pulled image might report “Running” even if the internal service is failing. Podman addresses this with Health Checks.
If a health check is configured, Podman keeps the old image as a fallback. If the new container fails the health check, it automatically rolls back to the previous version.
podman run -d --name secure-app \
--label "io.containers.autoupdate=image" \
--health-cmd="curl http://localhost/ || exit 1" \
--health-interval=5s \
--health-retries=3 \
--health-on-failure=rollback \
docker.io/library/nginx:latest
With the --health-on-failure=rollback flag, you can sleep soundly. If the update fails, the system will automatically “step back” to keep the website live.
Management and Debugging
To see what the system has done, check the systemd logs:
journalctl --user -u podman-auto-update.service
A small note: If you log out of SSH, user services are often terminated. Enable “linger” mode to ensure containers keep running in the background:
sudo loginctl enable-linger $USER
Real-world Experience: Mistakes That Can Cost You
After several “stumbles,” I’ve learned three hard-earned lessons when using auto-update:
- Never use the :latest tag for Databases: You don’t want Postgres to automatically jump from version 13 to 16 and break your entire data structure. Use specific tags like
:13. - Handle junk images: Every update leaves behind old (dangling) images. Add a cron job to run
podman image prune -fweekly to clean up storage. - Private Registry: Ensure you are logged in and the
auth.jsonfile is in the right location so systemd has access when you aren’t logged in.
This approach is more professional and fits the SysAdmin mindset better than manually typing pull commands every day. Good luck with your setup!

