Diagnostic First Steps
Before diving into specific errors, always start with these two commands when Watchtower Docker is not working:
# Step 1: Check if Watchtower is running
docker ps | grep watchtower
# Step 2: Read the logs
docker logs watchtower --tail 100
# Step 3: Enable debug mode for more detail
docker run -d \
--name watchtower-debug \
-v /var/run/docker.sock:/var/run/docker.sock \
-e WATCHTOWER_DEBUG=true \
containrrr/watchtower --run-once
The --run-once flag is invaluable for troubleshooting — it runs a single check cycle and exits, letting you see exactly what Watchtower finds without leaving a daemon running.
Error: Cannot Connect to the Docker Daemon
This is the most common Watchtower Docker error. The full message looks like:
Error response from daemon: dial unix /var/run/docker.sock: connect: permission denied
# OR
Cannot connect to the Docker daemon at unix:///var/run/docker.sock
Cause and Fix
Watchtower needs access to the Docker socket. The fix is to mount it correctly:
# docker run — add the -v flag
docker run -d \
--name watchtower \
-v /var/run/docker.sock:/var/run/docker.sock \ # THIS LINE IS REQUIRED
containrrr/watchtower
# Docker Compose — add the volumes block
services:
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock # THIS LINE IS REQUIRED
If the socket is mounted but you still get permission errors:
# Check socket permissions on the host
ls -la /var/run/docker.sock
# Should show: srw-rw---- 1 root docker ...
# Add your user to the docker group (requires re-login)
sudo usermod -aG docker $USER
# OR run Watchtower as root (less secure but simpler)
docker run -d --user root -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower
Watchtower Not Updating Containers
When Watchtower Docker is not updating containers, the cause is almost always one of these five issues:
1. Container is using a pinned digest
# This will NEVER be updated (sha256 digest is immutable):
image: nginx@sha256:abc123...
# This WILL be updated (mutable tag):
image: nginx:latest
image: nginx:1.25
2. WATCHTOWER_LABEL_ENABLE is true but container lacks the label
See the complete labels guide for opt-in and opt-out label patterns.
# If this env var is set:
- WATCHTOWER_LABEL_ENABLE=true
# Then each container you want updated needs this label:
labels:
- "com.centurylinklabs.watchtower.enable=true"
3. Container has the disable label
# This container is explicitly excluded from Watchtower:
labels:
- "com.centurylinklabs.watchtower.enable=false"
4. No newer image exists on the registry
Watchtower checks if the registry digest differs from the local digest. If the registry has not pushed a new image, Watchtower correctly does nothing. Verify by manually pulling:
docker pull nginx:latest
# "Status: Image is up to date" = no new version
# "Status: Downloaded newer image" = update available (Watchtower should catch this)
5. Registry authentication failing silently
# Enable debug to see auth errors
docker run -d -e WATCHTOWER_DEBUG=true \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower --run-once
Unauthorized / Registry Authentication Errors
The Watchtower Docker unauthorized error appears when Watchtower cannot authenticate with a registry to check for updates.
# Error messages that indicate auth problems:
level=error msg="Could not fetch tag" error="unauthorized: access to the requested resource is not authorized"
level=error msg="401 Unauthorized"
level=error msg="403 Forbidden"
Fix: Mount Docker Credentials
# Step 1: Log in on the host
docker login
# For private registry:
docker login registry.example.com
# Step 2: Mount the credentials into Watchtower
volumes:
- /root/.docker/config.json:/config.json:ro
# If running as non-root:
# - /home/username/.docker/config.json:/config.json:ro
Fix: Environment Variable Credentials
environment:
- REPO_USER=myDockerHubUsername
- REPO_PASS=myDockerHubPassword
# For private registry:
- REPO_USER__registry.example.com=user
- REPO_PASS__registry.example.com=password
Docker Hub Rate Limit (429 Too Many Requests)
# Rate limit errors look like:
level=error msg="toomanyrequests: You have reached your pull rate limit"
# Fix: Authenticate to Docker Hub (200 pulls/6h vs 100 for anonymous)
docker login
# OR set REPO_USER / REPO_PASS in Watchtower environment
# AND increase WATCHTOWER_POLL_INTERVAL to reduce frequency
Watchtower Keeps Restarting
When Watchtower Docker keeps restarting, it is crashing on startup. Check what's causing the crash:
# View crash reason
docker logs watchtower
# Common crash messages and fixes:
# "invalid duration" — WATCHTOWER_TIMEOUT value is malformed (use "30s" not "30")
# "failed to parse schedule" — WATCHTOWER_SCHEDULE cron is invalid (must be 6 fields)
# "permission denied: /var/run/docker.sock" — socket not mounted or no permission
# "no such file or directory: /config.json" — mounted credentials file doesn't exist on host
0 4 * * * will fail. The correct 6-field version is 0 0 4 * * *. See the scheduling guide for complete cron syntax and examples.Watchtower Docker Login Issues
Issues with Watchtower Docker login typically manifest as silent failures — Watchtower starts fine but skips updating private images without explanation.
# Debug login issues
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /root/.docker/config.json:/config.json:ro \
-e WATCHTOWER_DEBUG=true \
containrrr/watchtower --run-once
# Look for lines like:
# level=debug msg="Retrieving token" registry="registry.example.com"
# level=debug msg="Unable to retrieve token" error="..."
AWS ECR / GCR / GHCR Authentication
# AWS ECR — credentials rotate every 12 hours, use ecr-credential-helper
# Install on host: https://github.com/awslabs/amazon-ecr-credential-helper
# Then ~/.docker/config.json will use the helper automatically
# GitHub Container Registry (ghcr.io)
echo $GHCR_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# Then mount config.json into Watchtower
# Google Container Registry (gcr.io) — use gcloud auth
gcloud auth configure-docker
Is Watchtower Abandoned or Deprecated?
The original containrrr/watchtower project was archived on December 17, 2025. The GitHub repository is now read-only and will not receive new releases or security patches. See What Happened to Watchtower Docker for the full story.
The actively maintained replacement is nickfedor/watchtower — a fully API-compatible community fork by Nicholas Fedor with continued releases and security patches. Migration takes under 2 minutes.
If you're evaluating alternatives beyond the Watchtower ecosystem, see our 2026 alternatives comparison covering Diun, What's Up Docker, dockcheck, and Portainer.
Watchtower Docker Security — Is It Safe?
Watchtower requires access to the Docker socket, which is equivalent to root access on the host. Mitigations:
# Use a socket proxy (Tecnativa Docker Socket Proxy)
# Limits what Watchtower can do with the socket
services:
socket-proxy:
image: tecnativa/docker-socket-proxy
environment:
- CONTAINERS=1
- POST=1
- IMAGES=1
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- socket-proxy
watchtower:
image: containrrr/watchtower
environment:
- DOCKER_HOST=tcp://socket-proxy:2375
networks:
- socket-proxy
Watchtower in Production — Common Questions
Teams evaluating Watchtower Docker production use often ask: is it safe to use in production? The answer depends on your risk tolerance:
- For homelab / self-hosted apps: Watchtower with
WATCHTOWER_CLEANUP=trueand a daily schedule is safe and highly recommended. See the self-hosted apps guide for per-app safety ratings. - For non-critical production services: Use
WATCHTOWER_MONITOR_ONLY=true+ notifications to detect updates, then apply manually or via CI/CD. - For critical production: Use label-based exclusion to protect databases and stateful services. Consider Watchtower as a notification tool only — use your CI/CD pipeline for actual deployments.
Frequently Asked Questions
This error means Watchtower cannot access the Docker socket. Add -v /var/run/docker.sock:/var/run/docker.sock to your docker run command or the volumes: block in Docker Compose. Also ensure the socket file exists on the host and that the Watchtower container has permission to read it — either run as root or add the container user to the docker group.
The most common reasons are: (1) the image is pinned to a digest (sha256) rather than a mutable tag, (2) WATCHTOWER_LABEL_ENABLE=true is set but the container lacks the enable label, (3) the container has com.centurylinklabs.watchtower.enable=false, or (4) there genuinely is no newer image on the registry. Enable WATCHTOWER_DEBUG=true to see exactly why containers are being skipped.
Run docker login on the host, then mount the credentials file into Watchtower: -v /root/.docker/config.json:/config.json:ro. Alternatively set REPO_USER and REPO_PASS environment variables. For Docker Hub rate limits (429 errors), authenticate to get 200 pulls/6h instead of 100, and set a longer WATCHTOWER_POLL_INTERVAL.
Check docker logs watchtower to see the crash reason. Common causes: missing Docker socket mount ("permission denied"), invalid WATCHTOWER_SCHEDULE cron expression (must be 6 fields with seconds first), malformed WATCHTOWER_TIMEOUT value (use 30s not 30), or a config.json credentials file path that doesn't exist on the host.