Contactez-nous

Nettoyage et maintenance d'un registry (garbage collection)

Apprenez à effectuer la garbage collection sur votre registry Docker privé pour récupérer l'espace disque occupé par les couches et manifestes non référencés. Maintenez votre registry performant.

L'accumulation silencieuse : le problème des données orphelines

Au fil du temps, un registry Docker, qu'il soit privé ou utilisé comme proxy, accumule des données. Chaque `docker push` transfère des couches (blobs) et des métadonnées (manifests). Lorsqu'une image est mise à jour (poussée avec le même tag mais un contenu différent) ou lorsque des images sont supprimées via l'API du registry (si activée), les anciennes couches et les anciens manifests ne sont pas immédiatement supprimés du stockage sous-jacent.

Ces données deviennent "orphelines" ou "non référencées" : elles existent toujours sur le disque (ou dans le stockage S3, etc.) mais ne sont plus liées à aucun tag d'image activement référencé. Cette accumulation peut consommer une quantité significative d'espace de stockage au fil du temps, augmentant les coûts et potentiellement ralentissant certaines opérations du registry.

Il est donc crucial de disposer d'un mécanisme pour identifier et supprimer ces données inutilisées afin de maintenir l'efficacité et la propreté du registry. Ce processus est appelé la garbage collection (collecte des déchets).

Comprendre le processus de garbage collection du registry

Le registry Docker (version 2 et ultérieures) intègre un outil de garbage collection. Ce processus fonctionne généralement en deux étapes principales :

1. Phase de Marquage (Mark) : Le collecteur parcourt tous les manifests actuellement référencés par les tags dans tous les dépôts du registry. Il identifie toutes les couches (blobs) qui sont pointées par ces manifests actifs. Toutes les autres données (manifests non tagués, couches non référencées par aucun manifest actif) sont considérées comme candidates à la suppression.2. Phase de Balayage (Sweep) : Le collecteur supprime effectivement les manifests et les blobs marqués comme inutilisés lors de la phase précédente. C'est cette étape qui libère réellement l'espace de stockage.

Pour que la phase de balayage puisse effectivement supprimer des blobs, l'option de suppression (`delete`) doit être activée dans la configuration du registry. Si elle n'est pas activée, le garbage collector identifiera les éléments à supprimer mais ne les effacera pas du stockage.

Exécuter la commande de garbage collection

La garbage collection s'exécute via une commande à l'intérieur du conteneur registry. En supposant que votre conteneur registry s'appelle `mon-registry`, la commande typique est :

docker exec mon-registry bin/registry garbage-collect /etc/docker/registry/config.yml

Décortiquons cette commande :

  • docker exec mon-registry : Exécute une commande à l'intérieur du conteneur nommé `mon-registry`.
  • bin/registry : C'est l'exécutable principal du registry à l'intérieur du conteneur.
  • garbage-collect : C'est la sous-commande spécifique pour lancer le processus de nettoyage.
  • /etc/docker/registry/config.yml : C'est le chemin vers le fichier de configuration du registry à l'intérieur du conteneur. Le collecteur a besoin de lire cette configuration pour connaître les détails du stockage (où trouver les données) et vérifier si les suppressions sont activées.

L'exécution de cette commande peut prendre du temps, en fonction de la taille de votre registry et du nombre d'objets à vérifier et à supprimer. La sortie de la commande indiquera les différentes phases et les objets supprimés.

Prérequis crucial : mode lecture seule ou arrêt des écritures

C'est le point le plus critique et souvent négligé : la garbage collection ne doit jamais être exécutée pendant que le registry accepte des écritures (des `docker push`). Si un push se produit pendant que le collecteur analyse les références, il existe un risque de corruption de données ou de suppression accidentelle de couches qui viennent juste d'être poussées mais pas encore complètement référencées.

Pour éviter cela, vous avez deux options principales avant de lancer la commande `garbage-collect` :

1. Mettre le registry en mode lecture seule : C'est la méthode recommandée si vous voulez minimiser l'indisponibilité pour les opérations de `pull`. Vous pouvez modifier temporairement la configuration du registry pour désactiver les écritures ou utiliser un orchestrateur ou un load balancer en amont pour ne plus router les requêtes d'écriture vers le registry pendant la durée du nettoyage.2. Arrêter complètement le conteneur registry : C'est la méthode la plus simple si une courte interruption de service est acceptable. Vous arrêtez le conteneur, lancez la commande `garbage-collect` sur un conteneur temporaire pointant vers le même stockage et la même configuration, puis redémarrez le conteneur registry principal.
# Arrêter le registry principal
docker stop mon-registry

# Lancer la GC sur un conteneur temporaire
docker run --rm -it \
  -v "$(pwd)"/registry-data:/var/lib/registry \
  -v "$(pwd)"/config.yml:/etc/docker/registry/config.yml \
  registry:2 garbage-collect /etc/docker/registry/config.yml

# Redémarrer le registry principal
docker start mon-registry

Ignorer cette précaution peut entraîner une perte de données irréversible.

Configuration requise : activer les suppressions

Comme mentionné précédemment, pour que le garbage collector puisse effectivement libérer de l'espace disque en supprimant les blobs orphelins, l'option de suppression doit être explicitement activée dans votre fichier `config.yml` :

version: 0.1
# ... autres configurations ...
storage:
  # ... configuration du stockage (filesystem, s3, etc.) ...
  delete:
    enabled: true # <-- Cette ligne est essentielle !
# ... reste de la configuration ...

Si `delete: enabled: false` (ou si la section `delete` est absente), la commande `garbage-collect` s'exécutera, identifiera les objets orphelins (phase de marquage), mais ne les supprimera pas (la phase de balayage sera inefficace pour les blobs). Assurez-vous que cette option est bien activée si votre objectif est de récupérer de l'espace disque.

Fréquence et alternatives

La fréquence à laquelle vous devez exécuter la garbage collection dépend de l'activité de votre registry (fréquence des pushes et des mises à jour d'images). Pour un registry très actif, une exécution hebdomadaire ou mensuelle peut être nécessaire. Pour un usage moins intensif, une exécution trimestrielle ou semestrielle peut suffire.

Il est conseillé de planifier ces opérations pendant les périodes de faible activité pour minimiser l'impact sur les utilisateurs, compte tenu de la nécessité de passer en lecture seule ou d'arrêter le service.

Il est important de noter que de nombreuses solutions de registry managées (comme Amazon ECR, Google Artifact Registry, Azure Container Registry) ou des plateformes de gestion d'artefacts plus complètes (Harbor, Nexus) gèrent souvent le nettoyage des anciennes couches de manière plus transparente ou automatisée, allégeant ainsi cette charge de maintenance pour l'administrateur.

Points clés de la maintenance du registry

La garbage collection est une tâche de maintenance essentielle pour tout registry Docker auto-hébergé afin de récupérer l'espace disque consommé par les données orphelines.

Elle s'exécute via la commande `docker exec bin/registry garbage-collect /path/to/config.yml`.

Le prérequis le plus important est de s'assurer que le registry est en mode lecture seule ou arrêté pendant l'exécution de la commande pour éviter toute corruption de données.

Assurez-vous que l'option `storage.delete.enabled: true` est présente et activée dans votre `config.yml` pour que le nettoyage soit effectif.

Planifiez des exécutions régulières en fonction de l'activité de votre registry et considérez les solutions managées si vous souhaitez déléguer cette tâche de maintenance.