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
ℹ️
On rootless Docker, the socket path is different. Use $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.

Use 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 docker group or run with sudo. See troubleshooting guide.
  • No updates detected: Ensure your container images use floating tags like latest or stable (not pinned SHA digests).
  • Schedule not running at expected time: Mount /etc/timezone:/etc/timezone:ro to ensure the container uses your host's timezone.
  • Rate limit errors from Docker Hub: Authenticate with docker login to increase your pull rate limit, or set WATCHTOWER_API_TOKEN.

Frequently Asked Questions

What is the minimal watchtower docker-compose example?

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.

How do I only update specific containers in Docker Compose?

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.

Can Watchtower update itself via Docker Compose?

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.

What is the difference between WATCHTOWER_POLL_INTERVAL and WATCHTOWER_SCHEDULE?

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.

Does Watchtower work with Docker Compose v2?

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.

AC
Alex Chen
Docker Infrastructure Engineer · containrrr contributor
Alex has 9 years of experience designing container infrastructure for high-traffic applications. He contributes to the containrrr organization and has authored documentation for Watchtower, Shepherd, and Hostess. All code examples in this article are tested against Docker Engine 26.x.

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