Watchtower avec GHCR privé : authentification et sélection par labels

Configurer Watchtower pour tirer des images privées sur GitHub Container Registry et ne mettre à jour que les services voulus.

Série Watchtower + GHCR en production #2
Written by AI
#Docker #Watchtower #GHCR #Sécurité

1. Créer un token GitHub (PAT)

Crée un Personal Access Token (classic) avec le scope read:packages.

# Sur le serveur (même utilisateur que celui qui lance Watchtower)
echo '<TON_PAT>' | docker login ghcr.io -u <TON_USER_GITHUB> --password-stdin
# Vérifie:
cat ~/.docker/config.json
# Tu dois voir une entrée "ghcr.io" dans auths.

2. Monter les identifiants dans Watchtower

Par défaut, Watchtower lit les identifiants à la racine /config.json. Monte ton ~/.docker/config.json à cet emplacement :

services:
    watchtower:
    image: containrrr/watchtower
    command: --interval 300 --cleanup --debug --label-enable
    volumes:
        - /var/run/docker.sock:/var/run/docker.sock
        - /home/ubuntu/.docker/config.json:/config.json:ro  # adapte le chemin selon l’utilisateur
    restart: unless-stopped
  • label-enable : n’actualise que les conteneurs marqués d’un label explicite.

Activer Watchtower pour un service précis

Ajoute ce label au service cible (ex. ton blog) :

services:
    blog:
    image: ghcr.io/<user>/<repo>:main
    labels:
      com.centurylinklabs.watchtower.enable: "true"

Astuce : garde un tag stable (:main, :prod) que ta CI met à jour à chaque build. Watchtower compare les digests de ce tag.

4. Tester immédiatement

Tu peux déclencher un cycle unique pour vérifier que tout est OK :

docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /home/ubuntu/.docker/config.json:/config.json:ro \
containrrr/watchtower --run-once --debug --label-enable

Si tu vois des erreurs type 401/403 Unauthorized, c’est que les identifiants GHCR ne sont pas bien montés dans Watchtower (vérifie le chemin et l’utilisateur).

5. Pièges fréquents

  • Chemin des creds : Watchtower lit /config.json (et pas /root/.docker/config.json) sauf configuration spéciale.
  • Nom d’image : tout en minuscules sur GHCR (ghcr.io/user/repo:tag).
  • Tag inexistant : si tu pousses :main côté CI, assure-toi que le conteneur utilise bien :main.