Introduction: Why Container Automation Matters
Managing Docker containers can become a real challenge. Each container requires regular updates for security and functionality.
Manual updates are time-consuming and error-prone. 🔄
In this article, you'll learn how to fully automate the process. We'll use two powerful tools: Watchtower and Diun.
What you'll achieve:
- Automatic container updates without your intervention
- Notifications for new versions before updating
- Complete control over the update process
- Saved time and reduced errors
Let's get started! 🚀
What Are Watchtower and Diun
Watchtower - Your Automatic Updater
Watchtower is a container that monitors your Docker images. It checks for new versions in the registry.
When it discovers an update, Watchtower automatically:
- Pulls the new image
- Stops the old container
- Starts a new container with the same configuration
- Deletes the old image (optional)
Diun - The Notification System
Diun (Docker Image Update Notifier) works differently. This tool only monitors and notifies.
It doesn't change anything automatically. Instead, it sends notifications when updates are available.
Key Diun features:
- Checking multiple registry sources
- Support for various notification channels
- Flexible check scheduling
- Filtering specific images
When to Use Each Tool
Use Watchtower when:
- You want full automation ✅
- Working in development environment
- You need quick updates
- Containers are non-critical
Use Diun when:
- You want complete control over updates 🎯
- Working in production environment
- You need approval before changes
- You want to schedule updates
Combine both tools when:
- You have a mixed environment (dev + production)
- You want notifications AND selective automation
- Managing many containers with different needs
System Preparation
Prerequisites
Before you begin, make sure you have:
- Docker Engine 20.10 or newer
- Docker Compose v2 or newer
- Root or sudo access to the system
- Basic knowledge of Docker and YAML syntax
Version Check
Open a terminal and run:
docker --version
docker compose version
You should see the installed component versions. If Docker Compose is not found, install it.
Creating Working Directory
Create a structure for your configurations:
mkdir -p ~/docker-automation/{watchtower,diun}
cd ~/docker-automation
This structure will help you organize files logically. 📁
Watchtower Setup Step by Step
Basic Configuration
Create a docker-compose.yml file in the directory:
version: '3.8'
services:
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_POLL_INTERVAL=86400
- WATCHTOWER_INCLUDE_RESTARTING=true
- TZ=Europe/Sofia
Parameter explanation:
-
WATCHTOWER_CLEANUP- automatically deletes old images -
WATCHTOWER_POLL_INTERVAL- checks every 24 hours (in seconds) -
WATCHTOWER_INCLUDE_RESTARTING- updates restarting containers too -
TZ- timezone for correct logs
Adding Email Notifications
Update the configuration with email notifications:
services:
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_POLL_INTERVAL=86400
- WATCHTOWER_NOTIFICATIONS=email
- WATCHTOWER_NOTIFICATION_EMAIL_FROM=watchtower@yourdomain.com
- WATCHTOWER_NOTIFICATION_EMAIL_TO=admin@yourdomain.com
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.gmail.com
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=your-email@gmail.com
- WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=your-app-password
- TZ=Europe/Sofia
Important for Gmail: Use App Password, not regular password. 🔐
Selective Container Updates
You can mark which containers to update:
version: '3.8'
services:
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_POLL_INTERVAL=86400
- WATCHTOWER_LABEL_ENABLE=true
- TZ=Europe/Sofia
nginx:
image: nginx:latest
container_name: my-nginx
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=true"
ports:
- "80:80"
database:
image: postgres:15
container_name: my-database
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=false"
environment:
- POSTGRES_PASSWORD=secret
Only containers with watchtower.enable=true will update automatically.
Starting Watchtower
Run the following command in the directory with the file:
docker compose up -d
Check if it's working properly:
docker logs watchtower
You should see messages about started checks. ✅
Diun Setup Step by Step
Basic Diun Configuration
Create new directory and files:
mkdir -p ~/docker-automation/diun/data
cd ~/docker-automation/diun
Create diun.yml file:
watch:
workers: 10
schedule: "0 */6 * * *"
firstCheckNotif: false
defaults:
watchRepo: true
providers:
docker:
watchByDefault: true
notif:
telegram:
token: "YOUR_BOT_TOKEN"
chatIDs:
- "YOUR_CHAT_ID"
Configuration explanation:
-
schedule- checks every 6 hours (cron format) -
workers- number of parallel checks -
watchByDefault- monitors all containers automatically -
watchRepo- checks entire repository for tags
Creating Docker Compose File for Diun
Create docker-compose.yml in the same directory:
version: '3.8'
services:
diun:
image: crazymax/diun:latest
container_name: diun
restart: unless-stopped
volumes:
- ./diun.yml:/diun.yml:ro
- ./data:/data
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=Europe/Sofia
- LOG_LEVEL=info
- LOG_JSON=false
Setting Up Telegram Bot for Notifications
Telegram is an excellent way for quick notifications. 📱
Creating a bot:
- Open Telegram and find @botfather
- Send command
/newbot - Follow instructions and get the token
- Find your Chat ID via @userinfobot
Update diun.yml:
notif:
telegram:
token: "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
chatIDs:
- "987654321"
templateBody: |
🐋 Docker Image Update Available!
📦 Image: {{ .Entry.Image }}
🏷️ New Tag: {{ .Entry.Manifest.Tag }}
📅 Created: {{ .Entry.Manifest.Created }}
Setting Up Discord Webhook
Discord is another excellent option for team work:
notif:
discord:
webhookURL: "https://discord.com/api/webhooks/YOUR_WEBHOOK_URL"
mentions:
- "@everyone"
timeout: 10s
Creating Discord webhook:
- Open Server Settings → Integrations
- Create new Webhook
- Copy the URL
- Paste it in configuration
Starting Diun
Start the container:
docker compose up -d
Check the logs:
docker logs -f diun
First check starts immediately after startup. 🎉
Combining Watchtower and Diun
Optimal Strategy for Hybrid Environment
Here's how to combine both tools effectively:
version: '3.8'
services:
# Diun - monitors all containers
diun:
image: crazymax/diun:latest
container_name: diun
restart: unless-stopped
volumes:
- ./diun/diun.yml:/diun.yml:ro
- ./diun/data:/data
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=Europe/Sofia
# Watchtower - updates only marked containers
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_POLL_INTERVAL=86400
- WATCHTOWER_LABEL_ENABLE=true
- WATCHTOWER_NOTIFICATIONS=shoutrrr
- WATCHTOWER_NOTIFICATION_URL=telegram://TOKEN@telegram?channels=CHAT_ID
- TZ=Europe/Sofia
# Development container - automatic updates
nginx-dev:
image: nginx:latest
container_name: nginx-dev
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=true"
ports:
- "8080:80"
# Production container - notifications only
nginx-prod:
image: nginx:alpine
container_name: nginx-prod
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=false"
ports:
- "80:80"
# Database - never updates automatically
postgres:
image: postgres:15-alpine
container_name: postgres-db
restart: unless-stopped
labels:
- "com.centurylinklabs.watchtower.enable=false"
environment:
- POSTGRES_PASSWORD=secure_password
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
Logic of this configuration:
- Diun monitors all containers and sends notifications
- Watchtower only updates development containers
- Production containers require manual updates
- You get notification before every automatic update
Advanced Techniques and Best Practices
Scheduling Updates at Specific Times
You can set exactly when Watchtower should check:
environment:
- WATCHTOWER_SCHEDULE=0 0 4 * * *
This cron expression means: every day at 4:00 AM. ⏰
Excluding Specific Containers
Add to containers you DON'T want to update:
labels:
- "com.centurylinklabs.watchtower.enable=false"
Monitoring Only Specific Tags
In diun.yml you can filter tags:
providers:
docker:
watchByDefault: true
watchStopped: false
defaults:
watchRepo: true
includeTags:
- "^\\d+\\.\\d+\\.\\d+$"
excludeTags:
- "latest"
- ".*-dev$"
This example monitors only semantic versions (1.2.3) and ignores latest and dev tags.
Backup Before Updating
You can add hook scripts:
environment:
- WATCHTOWER_LIFECYCLE_HOOKS=true
- WATCHTOWER_HTTP_API_UPDATE=true
Then create a script in the updating container:
#!/bin/sh
# Place in /etc/watchtower/pre-update
# Make backup before updating
docker exec postgres pg_dump -U postgres > backup_$(date +%Y%m%d).sql
Checking Health Status After Update
Add health check to containers:
nginx-prod:
image: nginx:alpine
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
Watchtower will wait for health check to pass successfully. 🏥
Troubleshooting and Common Issues
Watchtower Not Updating Containers
Checks:
- Make sure you have Docker socket access
- Check if labels are correctly set
- Review logs for errors
docker logs watchtower --tail 100
Diun Not Sending Notifications
Possible causes:
- Wrong API token or Webhook URL
- Firewall blocking outgoing connections
- Incorrect cron schedule configuration
Testing notifications:
docker exec diun diun notif test
Containers Not Starting After Update
Solution: Add restart policy:
restart: unless-stopped
Check if volume mount paths are correct.
High System Load
If you have many containers:
# In diun.yml
watch:
workers: 5 # Reduce workers
schedule: "0 */12 * * *" # Less frequent checks
# For Watchtower
environment:
- WATCHTOWER_POLL_INTERVAL=172800 # Every 48 hours
Conclusion and Next Steps
Automating Docker containers saves time and reduces errors. 🎯
What you learned:
- How Watchtower and Diun work
- How to set them up step by step
- How to combine them effectively
- Best practices for production environment
Production recommendations:
- Always test updates in staging environment first
- Use Diun for critical systems
- Make regular backups before automatic updates
- Document your configuration
Next steps:
- Add monitoring with Prometheus/Grafana
- Integrate with CI/CD pipeline
- Set up centralized logging
- Automate backup processes
You now have all the tools for professional Docker container management! 🚀
Useful resources:
- Watchtower documentation: https://containrrr.dev/watchtower/
- Diun documentation: https://crazymax.dev/diun/
- Docker Compose reference: https://docs.docker.com/compose/
Original article in Bulgarian: Docker Compose магия: Как да автоматизирате обновяването на всичките си контейнери с Watchtower и Diun
Good luck with your automation! 💪
What's your preferred method for updating Docker containers? Share your experience in the comments! 👇
Top comments (0)