Why Two Watchtowers Fight Each Other
If you've ever tried starting a second Watchtower container on a host that already has one running, you may have noticed the first one gets stopped. This isn't a bug — it's intentional cleanup behavior. Watchtower assumes, by default, that it's the only instance managing that Docker host or Swarm, and treats any other Watchtower container as a stale leftover to be cleaned up.
That default makes sense for the common case (one Watchtower per host). It gets in the way the moment you have a real reason to run more than one — for example, separate production and staging container groups on the same box, each wanting a different update schedule or notification target.
Scopes: Giving Each Instance an Identity
The fix is scopes. A scope is just a name you assign to a Watchtower instance and to the containers it's allowed to manage. Instances only clean up other instances that share their scope — different scopes coexist peacefully.
Set the scope on the Watchtower instance itself via environment variable or CLI flag:
environment:
- WATCHTOWER_SCOPE=production
Then label both the Watchtower container and the application containers it should manage with the matching scope label:
com.centurylinklabs.watchtower.scope=production
Example: Production and Staging Side by Side
services:
watchtower-prod:
image: containrrr/watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_SCOPE=production
- WATCHTOWER_LABEL_ENABLE=true
- WATCHTOWER_SCHEDULE=0 0 4 * * *
labels:
- "com.centurylinklabs.watchtower.scope=production"
watchtower-staging:
image: containrrr/watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_SCOPE=staging
- WATCHTOWER_LABEL_ENABLE=true
- WATCHTOWER_POLL_INTERVAL=300
labels:
- "com.centurylinklabs.watchtower.scope=staging"
app-prod:
image: myapp:latest
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "com.centurylinklabs.watchtower.scope=production"
app-staging:
image: myapp:edge
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "com.centurylinklabs.watchtower.scope=staging"
Here, watchtower-prod only ever touches containers scoped production, checking once a day on a strict schedule. watchtower-staging only touches containers scoped staging, polling every 5 minutes for a faster feedback loop. Neither instance will stop the other, because their scopes don't match.
The Unscoped Trap
One rule catches people off guard: an unscoped Watchtower instance (no WATCHTOWER_SCOPE set at all) will still stop other Watchtower instances, regardless of what scope they're using. If you need a general-purpose, unscoped instance to coexist peacefully with scoped ones, set its scope explicitly to none:
environment:
- WATCHTOWER_SCOPE=none
This tells Watchtower "I am deliberately unscoped, don't treat me as a default cleanup authority over everything else."
Frequently Asked Questions
Not by default — Watchtower assumes it's the only instance and will stop any other it finds. Give each instance a unique scope via WATCHTOWER_SCOPE and label the containers each one should manage with a matching scope label.
com.centurylinklabs.watchtower.scope=<name>. Apply it both to the Watchtower instance's own container and to the application containers you want that instance to manage.
An unscoped instance will stop other running Watchtower instances regardless of their scope. If you need unscoped and scoped instances to coexist, explicitly set the unscoped instance's scope to none.