Update Automatically Docker Containers with Watchtower on Ubuntu
Docker has revolutionized software development by allowing applications to be packaged into standardized units. This simplifies deployment, scaling, and management. However, keeping Docker images up-to-date on a server can be a repetitive and time-consuming task. Manually pulling new image versions and restarting containers for each update is far from ideal.
Watchtower provides a convenient solution. It’s a containerized application that monitors running Docker containers for changes in the images they were initially created from. When Watchtower detects a change, it automatically restarts the associated containers, pulling the latest image and ensuring the application runs with the most recent version.
This guide provides a comprehensive walkthrough of installing and configuring Watchtower for automated container updates on Ubuntu 20.04/22.04.
Prerequisites
Before setting up Watchtower, ensure the following prerequisites are met:
- An Ubuntu 20.04/22.04 server.
- Docker installed and running.
- Some Docker containers already running on the server.
Once your Ubuntu server meets these criteria, you can proceed with installing Watchtower.
Step 1 – Install Watchtower
Watchtower is distributed as a Docker image, making installation straightforward. The image is available on Docker Hub.
First, pull the latest Watchtower image:
$ docker pull containrrr/watchtower
After the image downloads, run a Watchtower container:
$ docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower
Let’s break down the docker run
command options:
-d
: Runs the container in detached mode (in the background).--name watchtower
: Assigns the name "watchtower" to the container.-v /var/run/docker.sock:/var/run/docker.sock
: Mounts the Docker socket inside the container. This allows Watchtower to communicate with the Docker daemon and monitor other containers.containrrr/watchtower
: Specifies the Docker image to use.
This command creates and starts a Watchtower container, ready to monitor your other containers.
Step 2 – Configure Watchtower Notification Options
By default, Watchtower silently checks for image updates without notifications. You can configure notifications using environment variables during Watchtower container launch.
Notifications on Containers Updated
To receive notifications when Watchtower updates containers, use the -e WATCHTOWER_NOTIFICATIONS=email
environment variable.
Available notification options include:
email
: Sends email notifications.slack
: Sends notifications to a Slack channel.msteams
: Sends notifications to an MS Teams channel.gotify
: Sends notifications to a Gotify server.pushover
: Sends notifications via Pushover.
Example:
$ docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock -e WATCHTOWER_NOTIFICATIONS=email containrrr/watchtower
This enables email notifications for container updates.
Notifications on Watchtower Start/Exit
To receive notifications when Watchtower starts or exits, use -e WATCHTOWER_NOTIFICATIONS_LEVEL=start-exit
:
$ docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock -e WATCHTOWER_NOTIFICATIONS=email -e WATCHTOWER_NOTIFICATIONS_LEVEL=start-exit containrrr/watchtower
This sends notifications for container updates and Watchtower startup/shutdown events.
Notification Services Configuration
If notifications are enabled, configure the notification service using environment variables or by mounting YAML configuration files.
Email Configuration
For email notifications, you need:
WATCHTOWER_EMAIL_FROM
: The sender’s email address.WATCHTOWER_EMAIL_TO
: The recipient’s email address.WATCHTOWER_EMAIL_SERVER
: The SMTP server address.WATCHTOWER_EMAIL_SERVER_PORT
: The SMTP server port.WATCHTOWER_EMAIL_SERVER_USER
: The SMTP server username.WATCHTOWER_EMAIL_SERVER_PASSWORD
: The SMTP server password.
For Gmail:
$ docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock
-e WATCHTOWER_NOTIFICATIONS=email
-e WATCHTOWER_EMAIL_FROM="your_email@gmail.com"
-e WATCHTOWER_EMAIL_TO="recipient_email@example.com"
-e WATCHTOWER_EMAIL_SERVER=smtp.gmail.com
-e WATCHTOWER_EMAIL_SERVER_PORT=587
-e WATCHTOWER_EMAIL_SERVER_USER="your_email@gmail.com"
-e WATCHTOWER_EMAIL_SERVER_PASSWORD=gmail_password
containrrr/watchtower
Slack Configuration
For Slack notifications, you need:
WATCHTOWER_NOTIFICATIONS_SLACK_WEBHOOK_URL
: The Slack webhook URL.WATCHTOWER_NOTIFICATIONS_SLACK_CHANNEL
: The Slack channel name.
Example:
$ docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock
-e WATCHTOWER_NOTIFICATIONS=slack
-e WATCHTOWER_NOTIFICATIONS_SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx
-e WATCHTOWER_NOTIFICATIONS_SLACK_CHANNEL="#channel-name"
containrrr/watchtower
MS Teams Configuration
For MS Teams notifications, you need:
WATCHTOWER_NOTIFICATIONS_MSTEAMS_WEBHOOK_URL
: The MS Teams webhook URL.
Example:
$ docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock
-e WATCHTOWER_NOTIFICATIONS=msteams
-e WATCHTOWER_NOTIFICATIONS_MSTEAMS_WEBHOOK_URL=https://webhook.teams.microsoft.com/xxx
containrrr/watchtower
Using Configuration Files
Alternatively, define notification configurations in YAML files and mount them into the Watchtower container.
Configuration file paths:
/config/email.yaml
/config/slack.yaml
/config/msteams.yaml
Mount your custom YAML files over the default empty files.
For email notifications:
$ docker run -d --name watchtower
-v /var/run/docker.sock:/var/run/docker.sock
-v /path/to/email.yaml:/config/email.yaml
containrrr/watchtower
Where your email.yaml
contains:
email:
from: your_email@gmail.com
to: recipient_email@example.com
server: smtp.gmail.com
port: 587
user: your_email@gmail.com
password: gmail_password
This approach keeps configurations separate from the Watchtower container.
Step 3 – Control Which Containers Are Updated
By default, Watchtower monitors all running containers. You can exclude containers by name or label.
Exclude by Container Name
Use the --exclude
option with a regex filter for names:
$ docker run -d --name watchtower
-v /var/run/docker.sock:/var/run/docker.sock
containrrr/watchtower --exclude "my-container-name|another-container"
Exclude by Container Label
Label containers with com.centurylinklabs.watchtower.enable=false
to exclude them:
$ docker run -d --label com.centurylinklabs.watchtower.enable=false nginx
Include Only Matching Containers
Whitelist containers using --include
:
$ docker run -d --name watchtower
-v /var/run/docker.sock:/var/run/docker.sock
containrrr/watchtower --include "container-a|container-b"
Watchtower will only update container-a
or container-b
.
Step 4 – Change the Watchtower Polling Intervals
Watchtower checks for new images every few minutes by default. Customize the polling frequency.
Check for New Images
Use the --interval
option with a duration string:
$ docker run -d --name watchtower
-v /var/run/docker.sock:/var/run/docker.sock
containrrr/watchtower --interval 5m
This checks for new images every 5 minutes.
Restart Containers
By default, Watchtower waits 10 minutes after an image update before restarting containers. Modify the delay with --restart-delay
:
$ docker run -d --name watchtower
-v /var/run/docker.sock:/var/run/docker.sock
containrrr/watchtower --restart-delay 2m
This sets the restart delay to 2 minutes.
Step 5 – Automate Watchtower Startup
Ensure Watchtower starts automatically when the Docker daemon starts. Create a systemd unit file.
Create /etc/systemd/system/watchtower.service
with this definition:
[Unit]
Description=Watchtower - Auto update Docker containers
Requires=docker.service
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker start -a watchtower
ExecStop=/usr/bin/docker stop -t 2 watchtower
[Install]
WantedBy=multi-user.target
This starts the Watchtower container when the Docker daemon starts.
Reload systemd and enable the Watchtower service:
$ sudo systemctl daemon-reload
$ sudo systemctl enable watchtower
Watchtower will now run automatically on server restart.
Step 6 – Set Up Watchtower in Docker Compose
Run Watchtower as part of a Docker Compose stack.
Add a watchtower service to your docker-compose.yml
file:
version: "3"
services:
app:
image: myapp
ports:
- "8080:80"
watchtower:
image: containrrr/watchtower
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 30
This starts Watchtower alongside other services. The volumes
section mounts the Docker socket. The command
sets the check interval to 30 seconds.
Run docker-compose up
, and Watchtower will keep your images updated. This is another good use for Update Automatically Docker Containers with Watchtower on Ubuntu.
Conclusion
This guide covered installing and configuring Watchtower for automated Docker container updates.
Key takeaways:
- Watchtower automates Docker image updates.
- You can configure notifications for updates and Watchtower events.
- You can control which containers Watchtower monitors.
- You can customize the polling intervals.
- Watchtower can be automated with systemd or Docker Compose.
With Watchtower, managing container updates becomes simpler. It keeps your containers running the latest versions automatically. This guide on Update Automatically Docker Containers with Watchtower on Ubuntu should help with this.
Alternative Solutions for Automatic Docker Container Updates
While Watchtower provides a convenient solution, other approaches can achieve automatic Docker container updates. Here are two alternatives:
1. Using a CI/CD Pipeline with Webhooks
A CI/CD (Continuous Integration/Continuous Deployment) pipeline can be configured to automatically rebuild and redeploy Docker containers upon changes to the underlying application code or base images. This approach offers greater control and flexibility compared to Watchtower.
Explanation:
- Code Changes: When code changes are pushed to a Git repository (e.g., GitHub, GitLab, Bitbucket), a webhook triggers the CI/CD pipeline.
- Image Building: The pipeline builds a new Docker image using the updated code or base image.
- Image Tagging: The new image is tagged with a unique version or commit hash.
- Image Pushing: The image is pushed to a Docker registry (e.g., Docker Hub, GitLab Container Registry, AWS ECR).
- Deployment: The pipeline triggers a deployment process that updates the running containers with the new image. This can be achieved using tools like Docker Compose, Kubernetes, or custom scripts.
Code Example (GitLab CI/CD):
stages:
- build
- deploy
build:
stage: build
image: docker:latest
services:
- docker:dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
tags:
- docker
deploy:
stage: deploy
image: alpine/ssh-askpass:latest
before_script:
- apk add --update openssh-client bash
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | tr -d 'r' | ssh-keygen -q -N "" -f ~/.ssh/id_rsa
- chmod 400 ~/.ssh/id_rsa
- ssh-keyscan $SSH_HOST >> ~/.ssh/known_hosts
- chmod 400 ~/.ssh/known_hosts
script:
- ssh $SSH_USER@$SSH_HOST "docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA && docker stop my-container && docker rm my-container && docker run -d --name my-container -p 80:80 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
tags:
- docker
dependencies:
- build
only:
- main
Advantages:
- Greater Control: Provides fine-grained control over the update process.
- Automated Testing: Integrates automated testing into the pipeline.
- Rollback Capabilities: Simplifies rollback to previous versions.
- Version Control: Leverages Git for version control of both code and infrastructure.
Disadvantages:
- Complexity: Requires more setup and configuration compared to Watchtower.
- Infrastructure: Needs a CI/CD server (e.g., GitLab CI, Jenkins, CircleCI).
2. Using Docker Swarm or Kubernetes with Rolling Updates
Container orchestration platforms like Docker Swarm and Kubernetes offer built-in mechanisms for performing rolling updates of containers. This approach minimizes downtime and ensures a smooth transition to new versions.
Explanation:
- Deployment: Deploy the application as a service or deployment within the Swarm or Kubernetes cluster.
- Image Update: When a new image is available, update the service or deployment configuration with the new image tag.
- Rolling Update: The orchestration platform gradually replaces the old containers with new ones, one at a time or in batches. This ensures that the application remains available throughout the update process.
- Health Checks: The platform monitors the health of the new containers and rolls back to the previous version if any issues are detected.
Code Example (Docker Swarm):
# Update the service with the new image
docker service update --image your-registry/your-image:latest your-service
# Configure a rolling update strategy
docker service update --update-parallelism 1 --update-delay 10s your-service
Code Example (Kubernetes):
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: your-registry/your-image:v1
---
# To update the image:
kubectl set image deployment/my-deployment my-container=your-registry/your-image:v2
Advantages:
- Minimal Downtime: Rolling updates ensure continuous availability.
- Automated Rollbacks: Built-in health checks enable automated rollbacks.
- Scalability: Easily scales the application across multiple nodes.
- Self-Healing: Automatically restarts failed containers.
Disadvantages:
- Complexity: Requires knowledge of container orchestration concepts.
- Infrastructure: Needs a Docker Swarm or Kubernetes cluster.
- Overhead: Adds some resource overhead due to the orchestration platform.
These alternative solutions offer different trade-offs in terms of complexity, control, and infrastructure requirements. The best approach depends on the specific needs and constraints of your application and environment. This method also automates Update Automatically Docker Containers with Watchtower on Ubuntu.