Skip to content
Go back

Watchtower: Safe Container Auto-Updates

By SumGuy 5 min read
Watchtower: Safe Container Auto-Updates

The Dilemma

You’ve got a bunch of Docker containers running. Some have security updates. Some have bug fixes. You know you should update them. But updating means downtime, and what if the new version breaks something?

Watchtower solves this by automatically pulling new images and restarting containers. But “automatically” is dangerous if you’re not careful. You can wake up to broken apps because a new version had incompatible changes.

Here’s how to do it safely.

What Watchtower Does

Watchtower monitors your Docker images. When a new version is pushed to the registry, it:

  1. Pulls the new image
  2. Stops the old container
  3. Starts a new one with the new image
  4. Cleans up the old image

All automatic. No human intervention needed.

The catch: if that new version breaks your app, you’re down until you notice and rollback.

Safe Configuration

Instead of blindly updating everything, use these strategies:

Strategy 1: Update only specific containers

version: '3.8'
services:
watchtower:
image: containrrr/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --cleanup app nginx mysql-backup
environment:
WATCHTOWER_SCHEDULE: "0 3 * * *"
WATCHTOWER_NOTIFICATION_URL: "ntfy://example.com/watchtower-alerts"

The command line tells Watchtower to only update containers named app, nginx, and mysql-backup. Leave the database container alone.

Strategy 2: Don’t update untagged containers

Never run latest. Always specify a version:

# Bad
services:
postgres:
image: postgres
# Good
services:
postgres:
image: postgres:15.4

With a pinned version, Watchtower won’t update your database unless you explicitly change the tag in compose.

services:
postgres:
image: postgres:15.4
# Auto-update ok — not critical infrastructure
web-app:
image: myapp:latest
watchtower:
image: containrrr/watchtower:latest
command: --cleanup web-app

Only the web app gets updated. The database is locked to 15.4.

Rollback Strategy

If an update breaks something, you need a fast rollback. The key: keep the old image around.

Terminal window
docker images

Shows you what images you have. Say an update broke your app:

Terminal window
docker ps -a

Find the old container. Then:

Terminal window
docker run -d \
--name app-backup \
-v app-data:/data \
myapp:old-tag

You’re now running the old tag. Done.

But Watchtower deletes old images by default. Disable that:

watchtower:
image: containrrr/watchtower:latest
command: --cleanup app
# Keep old images for 30 days
environment:
WATCHTOWER_CLEANUP: "true"
WATCHTOWER_REMOVE_VOLUMES: "false"

Wait, that’s not quite right. Watchtower deletes unused images after updating. To keep them:

watchtower:
image: containrrr/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --cleanup
# Don't remove old images
# (just don't pass --cleanup or use --no-cleanup)

Actually, simplest approach: use a tag that includes the date:

Terminal window
# In your CI/CD, tag images like this:
docker tag myapp:build myapp:2025-12-23
docker push myapp:2025-12-23

Then in Compose:

services:
app:
image: myapp:2025-12-23

When you need to rollback, just change the tag back:

services:
app:
image: myapp:2025-12-22

And restart:

Terminal window
docker-compose up -d

Notification on Update

Watchtower can notify you when it updates something. This is important — you want to know when things change.

watchtower:
image: containrrr/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# Update check at 3 AM
WATCHTOWER_SCHEDULE: "0 3 * * *"
# Send notifications
WATCHTOWER_NOTIFICATIONS: shoutrrr
WATCHTOWER_NOTIFICATION_URL: "ntfy://example.com/watchtower"
WATCHTOWER_NOTIFICATION_TEMPLATE: |
{{if eq .Status "updated"}}
Updated: {{ .Name }}
Old: {{ .ImageId }}
New: {{ .NewImageId }}
{{end}}

With ntfy.sh, you get a simple HTTP POST. You can also use:

Manual Testing Before Auto-Update

The safest approach: test updates manually first, then enable auto-update for proven versions.

  1. Spin up a test container with the new image
  2. Run your app for an hour, verify it works
  3. Once you’re confident, update Watchtower to use that version
Terminal window
# Test the new version
docker run -d --name app-test myapp:new-version
docker logs -f app-test
# If everything's good, update your Compose file
# Change the tag from latest to new-version
# Let Watchtower handle the rest

Dangerous Updates to Avoid

Some updates you should never auto-update:

For these, use manual updates:

postgres:
image: postgres:15.4
# No watchtower for this
app:
image: myapp:latest
# Ok for watchtower to update
redis:
image: redis:7.0-alpine
# No watchtower for this

Check What Watchtower Would Update

Before deploying Watchtower, see what it would actually update:

Terminal window
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--dry-run \
--debug

The --dry-run flag shows what would be updated without actually doing it.

The Schedule

watchtower:
environment:
# 3 AM daily
WATCHTOWER_SCHEDULE: "0 3 * * *"
# Or cron format: Sunday at 2 AM
# WATCHTOWER_SCHEDULE: "0 2 * * 0"

Pick a time when you’re likely awake if something goes wrong. Not the middle of your work day (too disruptive), but not so late you’ll be asleep if there’s an issue.

The Paranoid Version

If you don’t trust Watchtower to not break things:

watchtower:
image: containrrr/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
# Only update images, don't restart containers
WATCHTOWER_MONITOR_ONLY: "true"
WATCHTOWER_NOTIFICATIONS: gotify
WATCHTOWER_NOTIFICATION_URL: "https://gotify.example.com"

With MONITOR_ONLY, Watchtower just tells you when updates are available. You manually restart containers to pick them up.

Bottom line: Watchtower is great for keeping things up-to-date, but you need to think about what breaks and how fast you can fix it. Update frequently, but safely.


Share this post on:

Send a Webmention

Written about this post on your own site? Send a webmention and it may appear here.


Previous Post
Uptime Kuma: Status Pages, Alerts, and Knowing Before Your Users Do
Next Post
Chaos Engineering: Break Things on Purpose Before They Break Themselves

Related Posts