Pourquoi vos tags de conteneur vous mentent
Vous exécutez docker pull myapp:latest et vous pensez savoir exactement ce que vous obtenez. Mais ce n'est pas le cas. Ce tag pourrait pointer vers une image différente demain, ou il pointe déjà vers une image différente de celle d'il y a une heure. Le même tag, la même commande, mais un logiciel complètement différent en production.
Ce n'est pas un problème théorique. Des équipes ont passé des heures à déboguer des incidents de production pour découvrir que l'image qu'elles pensaient exécuter n'était pas celle réellement en cours d'exécution. Le tag disait une chose, mais le contenu était tout autre.
Où vivent les images
Avant de parler des tags et de leurs problèmes, il faut comprendre où les images conteneur résident réellement.
Lorsque vous construisez une image Docker sur votre poste, cette image n'existe que sur votre machine. Pour l'exécuter sur un serveur, dans un environnement de staging ou en production, vous avez besoin d'un endroit pour stocker et partager cette image. Cet endroit s'appelle un registry.
Considérez un registry comme un serveur de fichiers pour images conteneur, mais avec des fonctionnalités supplémentaires. Il gère les versions, vérifie l'intégrité et contrôle qui peut accéder à quoi. Quand vous exécutez docker pull nginx:latest, vous tirez depuis Docker Hub, qui est un registry public. N'importe qui peut en tirer, mais n'importe qui peut aussi y pousser, c'est pourquoi vous ne devriez pas vous fier aux images publiques pour la production.
La plupart des entreprises gèrent leur propre registry interne. Les options courantes incluent Harbor, Nexus, GitLab Container Registry ou Amazon ECR. Un registry interne vous offre trois choses :
- Traçabilité : Vous savez d'où vient chaque image. Pas d'images aléatoires provenant d'Internet.
- Vitesse : Le transfert d'images sur votre réseau interne est beaucoup plus rapide que depuis Internet.
- Contrôle : Vous décidez qui peut pousser des images et qui peut les tirer.
Sans registry, votre pipeline de déploiement n'a nulle part où mettre les images qu'il construit. Avec un registry, vous avez une source de vérité unique pour chaque image produite par votre équipe.
Les tags sont des étiquettes, pas des identifiants
Chaque image dans un registry possède un ou plusieurs tags. Un tag est une étiquette que vous attachez à une image pour marquer une version ou une variante spécifique. Vous voyez des tags partout : myapp:1.0.0, myapp:staging, myapp:latest.
Les tags sont pratiques. Ils offrent un moyen lisible par l'humain de référencer les images. Au lieu de retenir un long hash, vous tapez myapp:1.0.0 et vous obtenez l'image souhaitée.
Mais les tags ont un défaut fondamental : ils sont mutables. Vous pouvez changer à tout moment l'image vers laquelle pointe un tag. Aujourd'hui, myapp:latest pointe vers le hash d'image abc123. Demain, après une nouvelle construction, il pointe vers def456. Le tag reste le même, mais l'image change.
Cette mutabilité crée de vrais problèmes. Imaginez un scénario où votre environnement de staging exécute myapp:staging. Votre pipeline construit une nouvelle image, la tague comme staging et la pousse. Maintenant, le staging exécute le nouveau code. Mais que faire si quelqu'un écrase manuellement le tag staging avec une image différente ? Ou si votre pipeline tague accidentellement la mauvaise construction ? Vous n'avez aucun moyen de savoir quelle image s'exécute réellement dans le staging, sauf si vous vérifiez le digest.
Le pattern des tags immuables
La solution consiste à utiliser des tags immuables — des tags qui ne changent jamais après leur création. Une fois que vous assignez un tag à une image, ce tag reste avec cette image pour toujours.
Les tags immuables contiennent des informations uniques qui identifient une construction spécifique. Les patterns courants incluent :
- Version sémantique :
myapp:1.2.3 - Hash de commit Git :
myapp:a1b2c3d - Horodatage de construction :
myapp:20240515-1430 - ID d'exécution du pipeline :
myapp:build-456
Avec des tags immuables, vous pouvez retracer exactement quel code s'exécute dans n'importe quel environnement. Si quelqu'un signale un bug en production, vous regardez le tag, trouvez le hash de commit, et savez exactement quel code a produit cette image. Pas de suppositions, pas de "quelle version de latest est-ce ?"
Certaines équipes combinent les approches. Elles utilisent des versions sémantiques pour les releases, des hashs de commit pour les constructions de développement, et des horodatages pour les déploiements automatisés. La clé est la cohérence : chaque construction produit un tag unique qui n'est jamais réutilisé.
Les digests : la vérité
Les tags sont pratiques mais peu fiables. Si vous voulez une certitude absolue sur l'image que vous exécutez, vous devez utiliser les digests.
Chaque image conteneur a un digest. Un digest est un hash cryptographique du contenu de l'image. Il ressemble à quelque chose comme sha256:abc123def456.... Le digest est unique à cette image spécifique. Si le contenu de l'image change ne serait-ce que d'un octet, le digest change complètement.
Contrairement aux tags, les digests ne peuvent pas être déplacés ou réassignés. Le digest sha256:abc123 fera toujours référence à exactement la même image, pour toujours. Vous ne pouvez pas faire pointer ce digest vers une image différente, quoi que vous fassiez.
Lorsque vous tirez une image par son digest, vous êtes garanti d'obtenir exactement l'image que vous attendez. Il n'y a aucune ambiguïté, aucune chance d'obtenir une version différente.
# Ceci est sûr - vous obtenez exactement ce que vous avez demandé
docker pull myapp@sha256:abc123def456
Utiliser tags et digests ensemble dans les pipelines
En pratique, vous utilisez à la fois les tags et les digests ensemble. Les tags rendent les images lisibles par l'humain et faciles à référencer. Les digests fournissent la garantie que vous exécutez la bonne image.
Voici comment un pipeline typique gère cela :
- Construire l'image.
- La taguer avec un tag immuable (hash de commit ou version).
- Pousser l'image vers le registry.
- Enregistrer le digest dans vos métadonnées de déploiement.
- Lors de la promotion du staging vers la production, vérifier que le digest correspond exactement.
L'étape de vérification est critique. Lorsque vous promouvez une image du staging vers la production, vous ne devriez pas simplement vérifier le tag. Vous devriez vérifier que le digest est identique. Cela évite qu'une situation où quelqu'un écrase le tag de staging avec une image différente, et que cette mauvaise image soit promue en production.
Voici un exemple pratique pour récupérer le digest après avoir poussé une image, puis l'utiliser pour épingler un déploiement :
# Construire et pousser l'image avec un tag immuable
docker build -t myapp:build-456 .
docker push myapp:build-456
# Récupérer le digest de l'image poussée
digest=$(docker inspect --format='{{index .RepoDigests 0}}' myapp:build-456 | cut -d'@' -f2)
echo "Digest: $digest"
# Utiliser le digest dans un manifeste de déploiement Kubernetes
cat <<EOF > deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp@$digest
EOF
# Appliquer le déploiement
kubectl apply -f deployment.yaml
Cela garantit que chaque pod exécute exactement la même image, indépendamment de ce qui arrive aux tags dans le registry.
De nombreux outils de déploiement prennent en charge les déploiements basés sur les digests. Kubernetes, par exemple, vous permet de spécifier une image par digest plutôt que par tag :
spec:
containers:
- name: myapp
image: myregistry.com/myapp@sha256:abc123def456
Cela garantit que chaque pod exécute exactement la même image, indépendamment de ce qui arrive aux tags dans le registry.
Liste de contrôle pratique
Avant votre prochain déploiement, passez en revue ces vérifications :
- Chaque construction produit un tag immuable unique (hash de commit, version ou horodatage)
- Le tag
latestn'est jamais utilisé dans les déploiements en production - Votre pipeline enregistre le digest de chaque image qu'il construit
- La promotion d'image entre environnements vérifie le digest, pas seulement le tag
- Votre registry a des contrôles d'accès pour empêcher les poussées non autorisées
- Les anciennes images sont nettoyées régulièrement pour éviter l'accumulation de stockage
Ce qu'il faut retenir
Les tags sont pour les humains. Les digests sont pour les machines. Utilisez les tags pour vous faciliter la vie, mais utilisez les digests pour rendre vos déploiements fiables. Quand quelque chose tourne mal en production, vous voulez savoir exactement ce qui s'exécute. Un tag mutable ne vous le dira pas. Un digest le fera, à chaque fois.