What is Watchtower Docker Compose?
The Watchtower Docker Compose pattern is the most widely used way to deploy containrrr/watchtower in production. Instead of running Watchtower as a standalone docker run command, you declare it as a service inside your existing docker-compose.yml file — right alongside your application containers.
This approach means Watchtower starts automatically when you run docker compose up -d, restarts if it crashes, and is configured entirely through the Compose file's environment block. No shell scripts, no manual commands on every server restart.
Prerequisites
- Docker Engine 20.10+ installed on your host
- Docker Compose v2 (plugin) or Compose v1 (standalone)
- Access to
/var/run/docker.sock(standard on Linux; see note below for rootless Docker) - Internet access to reach Docker Hub or your private registry
$XDG_RUNTIME_DIR/docker.sock instead of /var/run/docker.sock.Basic Watchtower Docker Compose Example
This is the minimal watchtower docker-compose configuration — copy it into any existing docker-compose.yml under the services key:
version: "3"
services:
watchtower:
image: containrrr/watchtower
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
With this configuration, Watchtower polls Docker Hub every 24 hours (86400 seconds, the default interval) and updates all running containers when newer images are found.
Full Production Docker Compose Configuration
The following watchtower docker compose configuration adds automatic cleanup, custom notifications, and a nightly update schedule — the recommended production setup:
version: "3.8"
services:
# Your application services
app:
image: myapp:latest
restart: unless-stopped
ports:
- "3000:3000"
nginx:
image: nginx:latest
restart: unless-stopped
ports:
- "80:80"
# Watchtower service
watchtower:
image: containrrr/watchtower
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/timezone:/etc/timezone:ro
environment:
# Remove old images after update (recommended)
- WATCHTOWER_CLEANUP=true
# Check for updates every 6 hours (21600 seconds)
- WATCHTOWER_POLL_INTERVAL=21600
# Send Slack notifications on updates
- WATCHTOWER_NOTIFICATIONS=slack
- WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK
- WATCHTOWER_NOTIFICATION_SLACK_IDENTIFIER=watchtower
# Log level: debug, info, warn, error
- WATCHTOWER_DEBUG=false
# Only update containers with the watchtower.enable label
# - WATCHTOWER_LABEL_ENABLE=true
Watchtower Docker Compose Schedule (Cron)
Instead of a poll interval, you can use a watchtower docker compose schedule expressed as a 6-field cron expression to run at precise times:
environment:
# Run every day at 4:00 AM
- WATCHTOWER_SCHEDULE=0 0 4 * * *
# Run every Sunday at 2:00 AM
# - WATCHTOWER_SCHEDULE=0 0 2 * * 0
# Run every 6 hours
# - WATCHTOWER_SCHEDULE=0 0 */6 * * *
The 6-field cron format used by Watchtower is: seconds minutes hours day-of-month month day-of-week. This differs from standard 5-field cron — note the leading seconds field.
WATCHTOWER_SCHEDULE for production workloads where you want updates at a specific low-traffic time. Use WATCHTOWER_POLL_INTERVAL for simpler homelab setups where exact timing doesn't matter.Watchtower Cleanup in Docker Compose
Setting WATCHTOWER_CLEANUP=true is one of the most important configuration options. Without it, every container update leaves the old Docker image on disk. Over time, especially with frequent updates, this can consume gigabytes of storage.
When cleanup is enabled, Watchtower automatically removes the old image immediately after a container is restarted with the new one. The currently running image is always preserved.
environment:
- WATCHTOWER_CLEANUP=true # Remove old images after update
nickfedor/watchtower Docker Compose
If you require the community fork maintained by Nicholas Fedor, simply change the image name:
services:
watchtower:
image: nickfedor/watchtower # or nicholas-fedor/watchtower
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- WATCHTOWER_CLEANUP=true
The nickfedor/watchtower fork is API-compatible with containrrr/watchtower and uses the same environment variables. See our Docker Hub images guide for the full comparison.
Verifying the Setup
After running docker compose up -d, check Watchtower is running and viewing its logs:
# Check container status
docker compose ps
# View Watchtower logs
docker compose logs watchtower --follow
# Expected output:
# time="2026-05-26T04:00:00Z" level=info msg="Starting Watchtower and scheduling first run"
# time="2026-05-26T04:00:01Z" level=info msg="Found new nginx:latest image (sha256:...)"
# time="2026-05-26T04:00:05Z" level=info msg="Updated nginx:latest" container=nginx
Common Issues
- Permission denied on Docker socket: Add your user to the
dockergroup or run withsudo. See troubleshooting guide. - No updates detected: Ensure your container images use floating tags like
latestorstable(not pinned SHA digests). - Schedule not running at expected time: Mount
/etc/timezone:/etc/timezone:roto ensure the container uses your host's timezone. - Rate limit errors from Docker Hub: Authenticate with
docker loginto increase your pull rate limit, or setWATCHTOWER_API_TOKEN.
Frequently Asked Questions
The minimum is: image containrrr/watchtower, a volume mount of /var/run/docker.sock:/var/run/docker.sock, and restart: unless-stopped. With just these three lines Watchtower will check Docker Hub every 24 hours and update all running containers.
Set WATCHTOWER_LABEL_ENABLE=true in the Watchtower environment. Then add com.centurylinklabs.watchtower.enable: "true" as a label to only the services you want updated. All other containers will be ignored. See our labels guide for full details.
Yes. By default, Watchtower includes itself in the list of containers to update. When a new containrrr/watchtower image is released on Docker Hub, Watchtower will pull it and restart itself. To prevent self-updates, add the label com.centurylinklabs.watchtower.enable: "false" to the watchtower service.
WATCHTOWER_POLL_INTERVAL sets a recurring interval in seconds (e.g., 3600 = every hour). WATCHTOWER_SCHEDULE uses a 6-field cron expression for exact time-of-day scheduling. Use WATCHTOWER_SCHEDULE when you need updates at a specific time (like 4 AM) to avoid impacting production traffic. You cannot set both simultaneously.
Yes, fully. Watchtower works with both the legacy docker-compose (v1) command and the modern docker compose plugin (v2). The configuration syntax is identical. Watchtower monitors containers regardless of which tool created them — it watches running Docker containers at the daemon level, not the Compose file.
Ready to set up Watchtower Docker Compose?
Start with our visual dashboard to monitor every container update in real time — free forever, no credit card required.
Start Free Monitoring