The problem: Docker images aging in silence
On a production VPS, Docker containers often run for weeks or months without being updated. This is not negligence — there is simply no signal. The nginx:latest image you pulled in January is still there in September, carrying vulnerabilities that have since been patched.
The cost of inaction is documented: unpatched CVEs in base images are one of the most common entry vectors on self-hosted Docker infrastructure. Manual updates — connecting to the VPS, running docker pull, recreating the container — are the default practice. They are also the least reliable: you postpone, forget, and only update the "important" services.
Two tools have emerged to structure this process: Watchtower, which automates the update itself, and Diun (Docker Image Update Notifier), which sends an alert when a new image is available and leaves the action to your pipeline. They do not do the same thing, and confusing the two philosophies can cost you a production outage.
Watchtower: automatic updates, but archived since late 2025
Watchtower monitors your running containers, queries registries at regular intervals, and as soon as a new image is available, pulls the new tag, stops the existing container and recreates it with the same options — volumes, environment variables, network. All without human intervention.
What it does in practice:
- Configurable polling by duration (every N seconds) or cron expression
- Private registry support with authentication
- WATCHTOWER_NOTIFICATIONS mode to receive alerts without performing updates
- Docker label filtering to include or exclude specific containers
The risk in production is real. If a :latest image introduces an incompatible API change or breaking behavior, Watchtower will recreate your container with that image — without testing, without a maintenance window, potentially at 3 AM. The container restarts with the wrong version, and discovery happens through a monitoring alert or a support call.
Important status update: the Watchtower GitHub repository was archived by its maintainers on late 2025. It is now read-only. The last published version is v1.7.1. The project remains functional and existing Docker images continue to run, but it will no longer receive security fixes, new features, or support for future Docker versions. For a tool whose role is to update your images, the irony is not insignificant.
For development environments or homelabs where convenience outweighs stability, Watchtower remains a legitimate choice. For production, its archival reinforces a conclusion that already existed: automatic updates without a validation pipeline are an operational risk.
Watchtower in notify-only mode
If you already use Watchtower and want to disable automatic updates while keeping notifications, set the variable WATCHTOWER_MONITOR_ONLY=true. The container monitors images and sends alerts but does not act. This is a useful transition configuration if you are migrating to Diun.
Diun: alerts only, you stay in control
Diun (Docker Image Update Notifier) approaches the problem from the other direction: it monitors your images on registries and sends you a notification when a new version is available. It does not act. Your containers keep running unchanged — the decision to update stays in your pipeline.
Licensed under MIT, Diun is actively developed: version la version actuelle was published on recently. The project covers a wide range of sources (Docker, Containerd, Kubernetes, Swarm, Nomad, Dockerfile, configuration file) and notification channels.
Supported notification channels:
- Email, Slack, Telegram, ntfy, Gotify
- Microsoft Teams, Discord, generic webhooks
- Healthchecks.io to monitor the watcher itself
What Diun does not do:
- It never pulls an image
- It never restarts a container
- It never modifies any configuration file
This philosophy is precisely what makes it suitable for production. When Diun signals that a new image is available, you can trigger your usual deployment pipeline — with its tests, prior backup, and maintenance window. You remain in a controlled posture.
Diun is also compatible with stacks managed by tools like Portainer, Coolify or Dokploy: it observes images without interfering with their orchestration.
When to choose one or the other
Scroll the table
| Context | Watchtower | Diun |
|---|---|---|
| Dev / staging environment | Acceptable (convenience) | Overkill |
| Prod with versioned tags (not :latest) | Avoid — recreates on same tag | Recommended |
| Prod with third-party API dependencies | Risky without prior testing | Recommended |
| Homelab / personal services | Practical | Good if alerts are active |
| Stack managed by Coolify, Dokploy, Portainer | Possible conflict with orchestrator | Recommended |
| Project without a deployment pipeline | Acceptable with monitor-only | Recommended with ntfy/Slack |
Installing Diun on a VPS: practical example
Installing Diun takes a few minutes with Docker Compose. The following example monitors all containers on the local Docker socket and sends notifications via ntfy.
Deploy Diun on your VPS
Create the docker-compose.yml file
Create a dedicated directory and the Compose file:
mkdir -p /opt/diun && cd /opt/diunContent of the
docker-compose.ymlfile:services: diun: image: crazymax/diun:latest restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock - ./data:/data environment: - TZ=Europe/Paris - LOG_LEVEL=info - DIUN_WATCH_WORKERS=20 - DIUN_WATCH_SCHEDULE=0 */6 * * * - DIUN_PROVIDERS_DOCKER=true - DIUN_PROVIDERS_DOCKER_WATCHSTOPPED=true - DIUN_NOTIF_NTFY_ENDPOINT=https://ntfy.example.com - DIUN_NOTIF_NTFY_TOPIC=diun-updatesReplace
ntfy.example.comwith the URL of your ntfy instance (self-hosted on the same VPS or external).Enable label-based monitoring (optional)
By default, Diun monitors all containers. For finer control, switch to label mode:
- DIUN_PROVIDERS_DOCKER_WATCHBYDEFAULT=falseThen add the label to the containers you want to monitor:
labels: - "diun.enable=true"This approach is useful for excluding system containers (proxies, databases) from notifications, and only monitoring application containers.
Start and verify
docker compose up -d docker compose logs -f diunDiun performs an initial discovery pass at startup. The logs confirm the images detected and the next monitoring cycle. A test notification can be triggered with:
docker compose exec diun diun notif testTrigger the update from your pipeline
When Diun sends a notification, the update should not be done by hand. The right approach is to trigger your usual pipeline — a Gitea webhook, a GitHub Action, or a Woodpecker job that pulls the new image, runs your tests, and recreates the container.
If you do not yet have a pipeline, the minimum viable option is a script called from the ntfy webhook:
#!/bin/bash # update-container.sh <container_name> CONTAINER=$1 docker compose -f /opt/${CONTAINER}/docker-compose.yml pull docker compose -f /opt/${CONTAINER}/docker-compose.yml up -dThe key point is that the update is triggered intentionally, not silently.
Going further: pin versions and stay in control
Automatic updates without a fixed tag are the real risk — whether you use Watchtower or a pipeline triggered by Diun. The :latest tag is an alias that can point to any version published by the maintainer. An update to :latest can introduce a breaking change without anything in your configuration changing.
The practice recommended by the Docker community:
Pin versions in your production docker-compose.yml files:
# Avoid in prod
image: nginx:latest
# Prefer a version tag
image: nginx:1.27Reserve :latest for development and staging environments, where a regression is detectable before it touches production.
With versioned images, Diun detects new releases (new tags) and notifies you — you choose the version to migrate to, update your docker-compose.yml, and deploy with full control. This is what the Docker Compose production checklist calls "declaring your dependencies explicitly".
If you manage multiple containers on the same VPS, a log monitoring tool like Dozzle usefully complements Diun: Diun monitors images upstream, Dozzle observes container logs after an update.
Diun also monitors stopped images
By default, Diun ignores stopped containers. Enable DIUN_PROVIDERS_DOCKER_WATCHSTOPPED=true to also monitor images of paused or stopped containers — useful if you manage batch services or maintenance containers that you restart periodically.
Key takeaways from this comparison
- Watchtower acts without asking — useful in dev, risky in prod, and archived since late 2025.
- Diun informs without acting — compatible with any existing deployment pipeline and actively maintained (la version actuelle).
- For production, Diun coupled with your pipeline is the most robust choice.
- Pinning versions in docker-compose.yml remains the foundation — neither Watchtower nor Diun replaces explicit tag management.
- If you have Watchtower in place,
WATCHTOWER_MONITOR_ONLY=truemode is an immediate transition to safer behavior.