Watchtower: Automatically Update Your Docker Containers

Watchtower: Automatically Update Your Docker Containers

Watchtower: Automatically Update Your Docker Containers

If you're running a homelab with Docker, you've probably felt the pain of manually updating containers. You check for new images, pull them down, stop the old container, recreate it with the same settings, and hope nothing breaks. Multiply that by a dozen services and you've got yourself a full afternoon of tedious work.

Enter Watchtower. It's a container that watches your other containers and automatically updates them when new images are available. Set it up once, and your containers stay fresh without you lifting a finger. Sounds great, right? Well, mostly. Let's dig into how it works, when you should use it, and when you probably shouldn't.

What Exactly Does Watchtower Do?

Watchtower is a Docker container that monitors your running containers. On a schedule you define, it checks the registry for updated images. When it finds one, it pulls the new image, gracefully stops the running container, and starts a new one with the exact same configuration. Your volumes, networks, and environment variables all carry over automatically.

The magic here is that Watchtower reads the container's existing configuration from Docker itself. You don't need to maintain any separate config files or remember what flags you used six months ago.

Getting Started

Deploying Watchtower is dead simple. Here's the basic docker-compose setup:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

That's it. Watchtower will now check for updates every 24 hours (the default) and update any container that has a newer image available.

The Case For Auto-Updates

Security patches land faster. When a vulnerability gets patched upstream, you want that fix running in your homelab as soon as possible. With Watchtower, you're not waiting until you remember to check for updates or have a free weekend.

Less maintenance overhead. Running a homelab should be fun, not a second job. Automating updates means you can focus on actually using your services instead of babysitting them.

Consistency across your stack. When updates happen automatically, all your containers stay roughly current. No more discovering that one service is running a version from 2022 because you forgot about it.

It just works (usually). For well-maintained projects with stable APIs, automatic updates rarely cause issues. Your Nginx Proxy Manager, Portainer, or Homepage dashboard will happily update themselves without drama.

The Case Against Auto-Updates

Breaking changes happen. Not every developer follows semantic versioning religiously. A minor version bump might introduce a config change that breaks your setup. If you wake up to a broken service, debugging becomes harder when you're not sure what changed.

Database containers are risky. Updating PostgreSQL, MySQL, or MongoDB automatically is playing with fire. Database upgrades often require migration steps, and an automatic update could leave your data in an inconsistent state. Seriously, don't auto-update your databases.

Rollbacks aren't automatic. If an update breaks something, Watchtower doesn't know. It won't roll back to the previous version. You'll need to manually intervene, and you'd better hope you remember what version you were running before.

Bandwidth and timing concerns. If Watchtower updates everything at 3 AM and pulls 20 large images, your internet connection might struggle. And if a service restarts during a critical task, you could lose work.

Configuration Options That Matter

The default setup is fine for testing, but you'll want to tune Watchtower for real use. Here's a more complete configuration:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_SCHEDULE=0 0 4 * * *
      - WATCHTOWER_TIMEOUT=30s
      - WATCHTOWER_INCLUDE_STOPPED=false
      - WATCHTOWER_REVIVE_STOPPED=false
    restart: unless-stopped

WATCHTOWER_CLEANUP removes old images after updating. Without this, your disk fills up with outdated images over time. Always enable this.

WATCHTOWER_SCHEDULE uses cron syntax to control when updates happen. The example above runs at 4 AM daily. Pick a time when you're not actively using your services but awake enough to notice if something breaks.

WATCHTOWER_TIMEOUT sets how long Watchtower waits for a container to stop gracefully before killing it. Increase this for services that take longer to shut down cleanly.

Excluding Containers From Updates

Here's where Watchtower gets smart. You can exclude specific containers from automatic updates using labels:

services:
  postgres:
    image: postgres:15
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

Now your database stays put while everything else updates automatically. This hybrid approach gives you the best of both worlds: convenience for stable services, control for critical ones.

Alternatively, you can flip the model entirely. Tell Watchtower to only update containers that explicitly opt in:

environment:
  - WATCHTOWER_LABEL_ENABLE=true

With this setting, Watchtower ignores everything unless it has the label com.centurylinklabs.watchtower.enable=true. This is the safer approach if you're cautious by nature.

Setting Up Notifications

Running Watchtower silently is a bad idea. You want to know when updates happen. Watchtower supports multiple notification backends, but the most practical options for homelabbers are email and webhooks (for Discord, Slack, or Gotify).

Here's a Discord webhook setup:

environment:
  - WATCHTOWER_NOTIFICATIONS=shoutrrr
  - WATCHTOWER_NOTIFICATION_URL=discord://token@webhookid

For email notifications:

environment:
  - WATCHTOWER_NOTIFICATIONS=email
  - WATCHTOWER_NOTIFICATION_EMAIL_FROM=watchtower@yourdomain.com
  - WATCHTOWER_NOTIFICATION_EMAIL_TO=you@yourdomain.com
  - WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.yourdomain.com
  - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587
  - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=username
  - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=password

Watchtower uses Shoutrrr under the hood, which supports dozens of notification services. Check their docs for the exact URL format for your preferred platform.

My Recommendation

Use Watchtower, but use it selectively. Enable auto-updates for stateless services like reverse proxies, dashboards, media servers, and monitoring tools. Exclude anything with persistent data that could be affected by schema changes, especially databases.

Set a reasonable schedule (early morning works well), enable cleanup, and always configure notifications. When an update happens, you want to know about it. That way, if something breaks, you can catch it quickly instead of discovering the problem days later.

The goal isn't to completely automate away your homelab maintenance. It's to handle the boring, repetitive parts so you can spend your time on the interesting stuff. Watchtower does that job well, as long as you respect its limitations.

Quick Reference

Here's a summary of the most useful environment variables:

  • WATCHTOWER_CLEANUP - Remove old images after update (true/false)
  • WATCHTOWER_SCHEDULE - Cron expression for update checks
  • WATCHTOWER_LABEL_ENABLE - Only update containers with opt-in label
  • WATCHTOWER_NOTIFICATIONS - Notification type (shoutrrr, email, slack, etc.)
  • WATCHTOWER_TIMEOUT - Graceful shutdown timeout
  • WATCHTOWER_POLL_INTERVAL - Seconds between checks (alternative to schedule)
  • WATCHTOWER_ROLLING_RESTART - Update one container at a time

Happy automating!