Update Automatically Docker Containers with Watchtower on Ubuntu

Posted on

Update Automatically Docker Containers with Watchtower on Ubuntu

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:

  1. Code Changes: When code changes are pushed to a Git repository (e.g., GitHub, GitLab, Bitbucket), a webhook triggers the CI/CD pipeline.
  2. Image Building: The pipeline builds a new Docker image using the updated code or base image.
  3. Image Tagging: The new image is tagged with a unique version or commit hash.
  4. Image Pushing: The image is pushed to a Docker registry (e.g., Docker Hub, GitLab Container Registry, AWS ECR).
  5. 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:

  1. Deployment: Deploy the application as a service or deployment within the Swarm or Kubernetes cluster.
  2. Image Update: When a new image is available, update the service or deployment configuration with the new image tag.
  3. 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.
  4. 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.

Leave a Reply

Your email address will not be published. Required fields are marked *