Watchtower: Automatically Update Docker Container Images

Keep your Docker container images up-to-date effortlessly with Watchtower! Learn how to update them automatically with our guide.

Docker is a popular containerization platform that allows you to easily package, distribute, and run applications in lightweight, portable containers. In light of this, one of the essential tasks in Docker container management is keeping container images up-to-date with the latest software patches, security fixes, and feature updates.

In this article, we introduce you to an exciting tool called “Watchtower,” which automates updating Docker container images. We will explore what Watchtower is, how it works, and how it can simplify your Docker workflow. So, let’s get started!

What is Watchtower?

Updating Docker container images can be a time-consuming and error-prone task, especially when managing a large number of containers across multiple hosts.

How do you update your Docker images so far?

docker stop <container_name>
docker rm <container_name>
docker pull <container_image>
docker run <container_name>Code language: HTML, XML (xml)

However, this approach can become a real challenge if you have dozens, not to mention hundreds of Docker images. What if you have multiple Dockerized hosts? You’ll agree that then the task seems almost impossible. This is where Watchtower comes to the rescue.

Watchtower is a lightweight, open-source container management tool that automates updating Docker container images. It monitors your Docker environment for changes in the available image versions and automatically pulls and updates containers with the latest images.

With Watchtower, you can keep your containers up-to-date without manual intervention, ensuring your applications run with the latest features and security patches.

How Watchtower Works?

Watchtower periodically checks the remote Docker image registry, such as Docker Hub or a private container registry, for updates to the container images currently running on your system.

When a new version of an image is available, Watchtower pulls the updated image. Then, it gracefully restarts the corresponding containers with the new image using the same options that were used when it was deployed initially.

By default, Watchtower checks every 86400 seconds (24 hours) if there are updates for the Docker images running containerized apps. According to your needs, however, the “WATCHTOWER_POLL_INTERVAL” and “WATCHTOWER_SCHEDULE” environment variables can change this interval.

In addition, Watchtower also provides options for scheduling updates, rolling updates, and configuring notifications, allowing you to customize the update process according to your requirements.

How to Use Watchtower

Watchtower is distributed as a Docker container, making installation as simple as possible. Because the app needs to interact with the Docker API to monitor the running containers, you need to mount the host’s “/var/run/docker.sock” into the Watchtower container using the “-v (–volume)” option.

So, you can run it with the following Docker command:

docker run -d \
  --name watchtower \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtowerCode language: JavaScript (javascript)
Run the watchtower container with Docker.
Run the watchtower container with Docker.

If you prefer to run Watchtower using Docker Compose, create an appropriate “docker-compose.yaml” file and place the following content in it:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sockCode language: JavaScript (javascript)

Then, fire up the container using the command below:

docker-compose up -d
Run the watchtower container with Docker Compose.
Run the watchtower container with Docker Compose.

If you need further guidance on how to use Docker Compose, our in-depth guide on the topic will significantly help.

That’s it! Your Watchtower container is started and begins monitoring all other running containers on your host, including itself, for Docker image updates.

If you check the Watchtower container logs (docker logs watchtower), you will see all its actions.

Watchtower container logs.
Watchtower container logs.

Of course, the necessary time must have elapsed for the information to accumulate, depending on the checking interval you have set.

Changing the Polling Interval

As previously stated, the default period for checking for new Docker images is 86400 seconds (24 hours). Watchtower gives us two options to control how frequently it will poll for new images, “WATCHTOWER_POLL_INTERVAL” and “WATCHTOWER_SCHEDULE.”

You can use whichever one you want, but not both simultaneously. So, let us show you how to use them.

Let’s say we want to set the default time interval for checking updates for new Docker images to 6 hours (21600 seconds). In that case, the Docker command we use to start Watchtower would be:

docker run -d \
  --name watchtower \
  -e WATCHTOWER_POLL_INTERVAL=21600 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtowerCode language: JavaScript (javascript)

Using Docker Compose, the “docker-compose.yaml” file would look like this:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_POLL_INTERVAL: 21600Code language: JavaScript (javascript)

The other environment variable is to use “WATCHTOWER_SCHEDULE,” which uses the Cron format, but instead of five fields, it uses six, adding one at the beginning for the seconds.

For example, set Watchtower to check every day at 4 AM for updated images, our Docker command would be:

docker run -d \
  --name watchtower \
  -e WATCHTOWER_SCHEDULE="0 0 4 * * *" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtowerCode language: JavaScript (javascript)

The Docker Compose equivalent is:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_SCHEDULE: "0 0 4 * * *"Code language: JavaScript (javascript)

Set Time Zone

If you are using scheduling like the one shown above, it is recommended to set a time zone. This guarantees that the run time matches what you want. Otherwise, Watchtower will use UTC as the default time zone.

To find the correct value, consult this list, find your location, and use the value in the “TZ” variable, for example, “America/New_York.”

docker run -d \
  --name watchtower \
  -e WATCHTOWER_SCHEDULE="0 0 4 * * *" \
  -e TZ=America/New_York
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtowerCode language: JavaScript (javascript)

The Docker Compose equivalent is:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_SCHEDULE: "0 0 4 * * *"
      TZ: America/New_YorkCode language: JavaScript (javascript)

Cleaning Up Old Docker Images

By default, Watchtower will not remove old Docker images when it downloads a new one. This can result in hundreds of orphaned ones taking up disk space over time.

To avoid this, you can run Watchtower with the “WATCHTOWER_CLEANUP” environment variable set to “true,” which will remove the old image after restarting a container with a new one.

docker run -d \
  --name watchtower \
  -e WATCHTOWER_CLEANUP=true \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtowerCode language: JavaScript (javascript)

Using Docker Compose, the “docker-compose.yaml” file would look like this:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_CLEANUP: trueCode language: JavaScript (javascript)

Excluding and Including Containers

By default, Watchtower monitors all containers. However, you may only want specific containers to be automatically updated. To achieve this, you must run those containers with the “com.centurylinklabs.watchtower.enable” label set to “true.”

docker run -d --label=com.centurylinklabs.watchtower.enable=true someimageCode language: JavaScript (javascript)

Then, run Watchtower with the “WATCHTOWER_LABEL_ENABLE” environment variable set to “true“:

docker run -d \
  --name watchtower \
  -e WATCHTOWER_LABEL_ENABLE=true \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtowerCode language: JavaScript (javascript)

If you’re a Docker Compose user:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_LABEL_ENABLE: trueCode language: JavaScript (javascript)

The opposite is also possible. For example, to mark only specific containers not to be monitored for Docker image updates, start them with the label “com.centurylinklabs.watchtower.enable=false” and then run Watchtower without setting the “WATCHTOWER_LABEL_ENABLE” environment variable.

Keeping Track of the Watchtower’s Actions

However, the automatic updating of Docker app images also poses some risks. That’s why we need to keep track of what’s happening on the server and what actions Watchtower takes with our dockerized applications.

A possible approach can be to inspect its logs regularly using the docker logs watchtower command. However, this requires regular engagement, and experience has shown that it is not the most reliable solution.

A significantly better way to accomplish this is to instruct Watchtower to email us when it acts. In that case, the Docker command we use to start Watchtower would be:

docker run -d --name watchtower \
    -e WATCHTOWER_NOTIFICATIONS=email \
    -e WATCHTOWER_NOTIFICATIONS_HOSTNAME="Lab1 Server" \
    -e [email protected] \
    -e [email protected] \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER=mail.yourdomain.com \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587 \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=fromaddress@yourdomain.com \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=yourpassword \
    -v /var/run/docker.sock:/var/run/docker.sock \
    containrrr/watchtowerCode language: JavaScript (javascript)

If you’re a Docker Compose user:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_NOTIFICATIONS: email
      WATCHTOWER_NOTIFICATIONS_HOSTNAME: "Lab1 Server"
      WATCHTOWER_NOTIFICATION_EMAIL_FROM: [email protected]
      WATCHTOWER_NOTIFICATION_EMAIL_TO: [email protected]
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER: mail.yourdomain.com
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: 587
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: [email protected]
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: yourpasswordCode language: JavaScript (javascript)

Of course, an SMTP server and the relevant credentials are required for this to work. In addition, don’t forget to replace all environment variables except “WATCHTOWER_NOTIFICATIONS: email” in the examples above with the appropriate values for your case.

Immediately after starting the container, you should receive a message in your mail similar to the one shown below.

Watchtower's automatic email notification.
Watchtower’s automatic email notification.

But let’s go one step further. Sending notifications can be nicely combined with the Watchtower’s “WATCHTOWER_MONITOR_ONLY” environment variable; as a result, none of the containers will be automatically updated, and we will only receive notifications about new Docker image updates that become available.

With this information, we can decide whether to perform the update manually and at the most appropriate time.

To achieve this, our Docker command would be:

docker run -d --name watchtower \
    -е WATCHTOWER_MONITOR_ONLY=true \
    -e WATCHTOWER_NOTIFICATIONS=email \
    -e WATCHTOWER_NOTIFICATIONS_HOSTNAME="Lab1 Server" \
    -e [email protected] \
    -e [email protected] \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER=mail.yourdomain.com \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587 \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=fromaddress@yourdomain.com \
    -e WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=yourpassword \
    -v /var/run/docker.sock:/var/run/docker.sock \
    containrrr/watchtowerCode language: JavaScript (javascript)

Docker Compose users must perform the following:

version: "3"
services:
  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      WATCHTOWER_MONITOR_ONLY: true
      WATCHTOWER_NOTIFICATIONS: email
      WATCHTOWER_NOTIFICATIONS_HOSTNAME: "Lab1 Server"
      WATCHTOWER_NOTIFICATION_EMAIL_FROM: [email protected]
      WATCHTOWER_NOTIFICATION_EMAIL_TO: [email protected]
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER: mail.yourdomain.com
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: 587
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: [email protected]
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: yourpasswordCode language: JavaScript (javascript)

Conclusion

There are several benefits to using Watchtower in your Docker workflow. First, it helps you keep your containers secure by automatically updating them with the latest security fixes and patches. This helps mitigate the risk of running containers with known vulnerabilities, which malicious actors can exploit.

Second, Watchtower simplifies updating container images, saving you time and effort compared to manual updates. It also reduces the risk of human error, which can occur when manually updating containers.

Finally, Watchtower provides flexibility and customization options, allowing you to configure the update process according to your specific needs and preferences.

Of course, you can use a whole host of other options to tailor Watchtower to your needs. To explore them in depth, visit the project’s website.

We hope that we were helpful to you. Any comments or suggestions are welcome in the comments section below.

Bobby Borisov

Bobby Borisov

Bobby, an editor-in-chief at Linuxiac, is a Linux professional with over 20 years of experience. With a strong focus on Linux and open-source software, he has worked as a Senior Linux System Administrator, Software Developer, and DevOps Engineer for small and large multinational companies.

Think You're an Ubuntu Expert? Let's Find Out!

Put your knowledge to the test in our lightning-fast Ubuntu quiz!
Ten questions to challenge yourself to see if you're a Linux legend or just a penguin in the making.

1 / 10

Ubuntu is an ancient African word that means:

2 / 10

Who is the Ubuntu's founder?

3 / 10

What year was the first official Ubuntu release?

4 / 10

What does the Ubuntu logo symbolize?

5 / 10

What package format does Ubuntu use for installing software?

6 / 10

When are Ubuntu's LTS versions released?

7 / 10

What is Unity?

8 / 10

What are Ubuntu versions named after?

9 / 10

What's Ubuntu Core?

10 / 10

Which Ubuntu version is Snap introduced?

The average score is 68%

2 Comments

  1. Hi Bobby, great article thank you. I have a question: I run all my containers in separate docker-compose files, example:
    /docker/nextcloud/docker-compose.yml
    /docker/uptime-kuma/docker-compose.yml
    etc etc etc.

    Normally I manually go to the folder and have a alias: alias dcr=’sudo docker-compose down && sudo docker-compose pull && sudo docker-compose up -d’ .

    How does watchtower interact with compose and its separate files? Or wouldn’t this be an issue?

    Thanks!

    • Hey VGE,

      First of all, apologies for responding late. Regarding your question – no, there won’t be any issues. What matters to Watchtower is identifying the labels it looks for on the container. It doesn’t matter how the container is deployed. It will take care of that container if the labels it’s looking for are there.

      Best,
      Bobby

Leave a Reply

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