Automatically Updating Docker Images

Automatically Updating Docker Images

If you have lots of Docker containers running on different servers, you should give some thought to updates. Personally, I run two private servers with a Traefik installation. Behind Traefik are various applications of different sizes, which I regularly update manually to stay as up to date as possible. This is important for closing security vulnerabilities and fixing software bugs. The same applies to Docker containers. They should always be kept up to date as well. However, Docker's simplicity often hides the software being used, which may be spread across multiple layers in a Docker image.

One approach I found for my private projects is the Watchtower tool. It can analyze running containers at a defined time or at intervals. For each container, it checks whether a new version of its Docker image is available. If one is available, the container is stopped and recreated using the new Docker image.

I have now tried this for a few days and have to say that it actually works well. Depending on the application, however, it may not make sense. For example, I have an application that does not automatically migrate its database schema when schema changes occur. You then have to start the Docker container once with a migration command. That would not work with Watchtower.

Fortunately, Watchtower can be configured to handle only containers with the label com.centurylinklabs.watchtower.enable=true. To enable this behavior, you need to pass the --label-enable option when starting Watchtower.

This is what it looks like in my setup:

version: "3.3"
services:
  watchtower:
    container_name: 'watchtower'
    image: containrrr/watchtower
    command: --cleanup --label-enable --schedule "0 23 5 \* \* \*"
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

In my setup, Watchtower is configured to update the images every day at 5:23 (UTC). You can also define an interval, such as "every hour". Keep in mind, though, that the tool downloads Docker images in the background to check them and makes the corresponding API calls. You can also hit the newly introduced Docker API rate limit here.

The container then still needs the label and must be restarted manually once.

For my Traefik server, for example, it looks like this:

version: '3'

services:
  traefik:
    container_name: traefik
    image: traefik:latest
    restart: unless-stopped
    ports:
      # The HTTP ports
      - "80:80"
      - "443:44"
      # The Web UI (enabled by --api)
      - "8080:8080"
      # imaps
      - "993:993"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "./volumes/letsencrypt:/letsencrypt"
      - "./volumes/etc/traefik:/etc/traefik"
    labels:
      - "traefik.enable=false"
      - "com.centurylinklabs.watchtower.enable=true"

Perhaps you like the idea, or perhaps you prefer another approach. I would be happy to hear from you in a comment.