Skip to main content
Tools

Automatically Update Your Docker Containers with Watchtower

A handy utility for automating your Docker container updates.

Abhishek Kumar

Warp Terminal

Imagine this: You’ve deployed a handful of Docker containers to power your favorite applications, maybe a self-hosted Nextcloud for your files, a Pi-hole for ad-blocking, or even a media server like Jellyfin.

Everything is running like a charm, but then you hit a common snag: keeping those containers updated.

When a new image is released, you’ll need to manually pull it, stop the running container, recreate it with the updated image, and hope everything works as expected.

Multiply that by the number of containers you’re running, and it’s clear how this quickly becomes a tedious and time-consuming chore.

But there’s more at stake than just convenience. Skipping updates or delaying them for too long can lead to outdated software running in your containers, which often means unpatched vulnerabilities.

These can become a serious security risk, especially if you’re hosting services exposed to the internet.

This is where Watchtower steps in, a tool designed to take the hassle out of container updates by automating the entire process.

Whether you’re running a homelab or managing a production environment, Watchtower ensures your containers are always up-to-date and secure, all with minimal effort on your part.

What is Watchtower?

Watchtower is an open-source tool that automatically monitors your Docker containers and updates them whenever a new version of their image is available.

It keeps your setup up-to-date, saving time and reducing the risk of running outdated containers.

But it’s not just a "set it and forget it" solution, it’s also highly customizable, allowing you to tailor its behavior to fit your workflow.

Whether you prefer full automation or staying in control of updates, Watchtower has you covered.

How does it work?

Watchtower works by periodically checking for updates to the images of your running containers. When it detects a newer version, it pulls the updated image, stops the current container, and starts a new one using the updated image.

The best part? It maintains your existing container configuration, including port bindings, volume mounts, and environment variables.

If your containers depend on each other, Watchtower handles the update process in the correct order to avoid downtime.

Deploying watchtower

Since you’re reading this article, I’ll assume you already have some sort of homelab or Docker setup where you want to automate container updates. That means I won’t be covering Docker installation here.

When it comes to deploying Watchtower, it can be done in two ways:

Docker run

If you’re just trying it out or want a straightforward deployment, you can run the following command:

docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower

This will spin up a Watchtower container that monitors your running containers and updates them automatically.

But here’s the thing, I’m not a fan of the docker run command.

It’s quick, sure, but I prefer stack approach rather than cramming everything into a single command.

Docker compose

If you facny using Docker Compose to run Watchtower, here’s a minimal configuration that replicates the docker run command above:

version: "3.8"

services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

To start Watchtower using this configuration, save it as docker-compose.yml and run:

docker-compose up -d

This will give you the same functionality as the docker run command, but in a cleaner, more manageable format.

Customizing watchtower with environment variables

Running Watchtower plainly is all good, but we can make it even better with environment variables and command arguments.

Personally, I don’t like giving full autonomy to one service to automatically make changes on my behalf.

Since I have a pretty decent homelab running crucial containers, I prefer using Watchtower to notify me about updates rather than updating everything automatically.

This ensures that I remain in control, especially for containers that are finicky or require a perfect pairing with their databases.

Sneak peak into my homelab

Take a look at my homelab setup: it’s mostly CMS containers for myself and for clients, and some of them can behave unpredictably if not updated carefully.

So instead of letting Watchtower update everything, I configure it to provide insights and alerts, and then I manually decide which updates to apply.

To achieve this, we’ll add the following environment variables to our Docker Compose file:

Environment Variable Description
WATCHTOWER_CLEANUP Removes old images after updates, keeping your Docker host clean.
WATCHTOWER_POLL_INTERVAL Sets how often Watchtower checks for updates (in seconds). One hour (3600 seconds) is a good balance.
WATCHTOWER_LABEL_ENABLE Updates only containers with specific labels, giving you granular control.
WATCHTOWER_DEBUG Enables detailed logs, which can be invaluable for troubleshooting.
WATCHTOWER_NOTIFICATIONS Configures the notification method (e.g., email) to keep you informed about updates.
WATCHTOWER_NOTIFICATION_EMAIL_FROM The email address from which notifications will be sent.
WATCHTOWER_NOTIFICATION_EMAIL_TO The recipient email address for update notifications.
WATCHTOWER_NOTIFICATION_EMAIL_SERVER SMTP server address for sending notifications.
WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT Port used by the SMTP server (commonly 587 for TLS).
WATCHTOWER_NOTIFICATION_EMAIL_USERNAME SMTP server username for authentication.
WATCHTOWER_NOTIFICATION_EMAIL_PASSWORD SMTP server password for authentication.

Here’s how the updated docker-compose.yml file would look:

version: "3.8"

services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    restart: always
    environment:
      WATCHTOWER_CLEANUP: "true"
      WATCHTOWER_POLL_INTERVAL: "3600"
      WATCHTOWER_LABEL_ENABLE: "true"
      WATCHTOWER_DEBUG: "true"
      WATCHTOWER_NOTIFICATIONS: "email"
      WATCHTOWER_NOTIFICATION_EMAIL_FROM: "[email protected]"
      WATCHTOWER_NOTIFICATION_EMAIL_TO: "[email protected]"
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER: "smtp.example.com"
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: "587"
      WATCHTOWER_NOTIFICATION_EMAIL_USERNAME: "your_email_username"
      WATCHTOWER_NOTIFICATION_EMAIL_PASSWORD: "your_email_password"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
I like to put my credentials in a separate environment file.

Once you run the Watchtower container for the first time, you'll receive an initial email confirming that the service is up and running.

Here's an example of what that email might look like:

After some time, as Watchtower analyzes your setup and scans the running containers, it will notify you if it detects any updates available for your containers.

These notifications are sent in real-time and look something like this:

This feature ensures you're always in the loop about potential updates without having to check manually.

Final thoughts

I’m really impressed by Watchtower and have been using it for a month now.

I recommend, if possible, to play around with it in an isolated environment first, that’s what I did before deploying it in my homelab.

The email notification feature is great, but my inbox now looks totally filled with Watchtower emails, so I might create a rule to manage them better. Overall, no complaints so far! I find it better than the Docker Compose method we discussed earlier.

Updating Docker Containers With Zero Downtime
A step by step methodology that can be very helpful in your day to day DevOps activities without sacrificing invaluable uptime.

What about you? What do you use to update your containers?

If you’ve tried Watchtower, share your experience, anything I should be mindful of?

Let us know in the comments!

Abhishek Kumar