DEV Community

Cover image for Docker Compose Magic: How to Automate All Your Container Updates with Watchtower and Diun
ITpraktika.com
ITpraktika.com

Posted on • Originally published at itpraktika.com

Docker Compose Magic: How to Automate All Your Container Updates with Watchtower and Diun

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
Enter fullscreen mode Exit fullscreen mode

Version Check

Open a terminal and run:

docker --version
docker compose version
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Check if it's working properly:

docker logs watchtower
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Setting Up Telegram Bot for Notifications

Telegram is an excellent way for quick notifications. 📱

Creating a bot:

  1. Open Telegram and find @botfather
  2. Send command /newbot
  3. Follow instructions and get the token
  4. 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 }}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Creating Discord webhook:

  1. Open Server Settings → Integrations
  2. Create new Webhook
  3. Copy the URL
  4. Paste it in configuration

Starting Diun

Start the container:

docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Check the logs:

docker logs -f diun
Enter fullscreen mode Exit fullscreen mode

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:
Enter fullscreen mode Exit fullscreen mode

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 * * *
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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$"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Watchtower will wait for health check to pass successfully. 🏥

Troubleshooting and Common Issues

Watchtower Not Updating Containers

Checks:

  1. Make sure you have Docker socket access
  2. Check if labels are correctly set
  3. Review logs for errors
docker logs watchtower --tail 100
Enter fullscreen mode Exit fullscreen mode

Diun Not Sending Notifications

Possible causes:

  1. Wrong API token or Webhook URL
  2. Firewall blocking outgoing connections
  3. Incorrect cron schedule configuration

Testing notifications:

docker exec diun diun notif test
Enter fullscreen mode Exit fullscreen mode

Containers Not Starting After Update

Solution: Add restart policy:

restart: unless-stopped
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
# For Watchtower
environment:
  - WATCHTOWER_POLL_INTERVAL=172800  # Every 48 hours
Enter fullscreen mode Exit fullscreen mode

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:


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)