« invalid reference format » est la façon dont Docker dit : « Je ne peux pas analyser ce que vous pensez être un nom d’image. » Ce n’est pas un problème réseau. Ce n’est pas un problème d’authentification. Bien souvent, ce n’est même pas un problème Docker.
C’est un problème de chaîne de caractères. Tout petit. Du genre qui arrive en production parce que ça a l’air correct lors d’une revue de code et ne casse que lorsqu’une variable est vide, qu’un espace s’insère, ou qu’un tag est formaté par une étape de build bien intentionnée.
Ce que l’erreur signifie vraiment (et pourquoi elle est si peu utile)
Docker lance « invalid reference format » lorsqu’il tente d’analyser une référence d’image (ou parfois un nom de conteneur, mais majoritairement c’est l’image) et que la chaîne ne correspond pas à ce que Docker considère comme une référence valide.
Le problème est que Docker expose l’erreur au mauvais niveau d’abstraction. Vous pensez « je lance un conteneur ». Docker pense « j’analyse une référence selon une grammaire ». Cette grammaire est stricte et, à certains endroits, étonnamment exigeante :
- Les composants du dépôt sont en minuscules, pour la plupart.
- Les tags ont leurs propres règles de caractères et limites de longueur.
- Les digests ont une syntaxe totalement différente et ne se mélangent pas n’importe comment avec les tags.
- Les espaces ne sont pas « ignorés ». Les espaces sont redoutables.
Les principales sources d’erreurs dans les systèmes réels :
- Espaces cachés (issus du copier/coller, du formatage YAML, des fins de ligne Windows, ou d’un script qui echo avec un retour chariot final).
- Variables vides qui compressent deux séparateurs en quelque chose d’illégal (comme
myapp:ourepo//image). - Majuscules dans les noms de dépôt (Docker est pointilleux ici par conception).
- Deux-points mal placés quand un port de registre et un tag sont impliqués.
- Guillemets « intelligents » et ponctuation non-ASCII provenant d’outils de chat et de tickets.
Voici l’état d’esprit pratique : traitez la référence d’image comme une entrée qui nécessite validation et normalisation, comme une URL. Parce que c’en est une — juste avec plus de pièges et des messages d’erreur moins utiles.
Petite blague #1 : Docker dit « invalid reference format » comme un grille-pain disant « erreur pain ». Techniquement correct, émotionnellement inutile.
Avant d’être tactique, définissons ce que Docker considère comme une référence. Une fois que vous comprenez cela, 90 % de ces incidents cessent d’être mystérieux et deviennent plutôt embarrassants de façon productive.
La véritable grammaire d’une référence d’image
Les références d’images Docker ne sont pas des chaînes libres. Elles suivent une structure implémentée par le parseur distribution/reference utilisé dans l’écosystème (Docker Engine, registres, outils). Conceptuellement :
- Nom (optionnellement avec un registre et un namespace)
- Tag optionnel introduit par
: - Digest optionnel introduit par
@
Le modèle mental que j’utilise en gestion d’incidents :
[registryhost[:port]/]path/name[:tag][@digest]- Où
path/nameest un ou plusieurs composants séparés par des slash. - Où
:taget@digestsont mutuellement exclusifs dans de nombreux flux (vous pouvez techniquement spécifier les deux dans certains contextes, mais évitez sauf si vous savez comment l’outil les résout).
Qu’est-ce qui est autorisé dans le nom de dépôt ?
Les noms de dépôts doivent en général être en minuscules et peuvent inclure des séparateurs comme _, ., et - à des positions spécifiques. Les slash divisent les composants de chemin. La règle la plus sûre en production est plus simple que la spec :
- Utilisez des lettres minuscules, des chiffres, des tirets et des slash pour le chemin du dépôt.
- N’utilisez pas de majuscules. N’argumentez pas. Vous y perdrez du temps et de la dignité.
Qu’est-ce qui est autorisé dans un tag ?
Les tags sont plus permissifs que les noms de dépôts mais ne sont pas arbitraires. Les erreurs les plus fréquentes :
- Inclure un slash dans un tag (
feature/new-ui) parce que les noms de branches Git contiennent des slash. - Inclure des espaces ou des retours à la ligne, généralement via des variables.
- Commencer un tag par un tiret dans certains contextes d’outillage (pas toujours illégal, mais souvent problématique à travers des scripts).
Si vous devez mapper des noms de branch sur des tags, nettoyez-les. Ne « espérez » pas que Docker l’acceptera.
Hôtes de registre et ports : le piège des deux-points
Le deux-points peut signifier « port » ou « tag », et Docker décide selon le contexte :
registry.example.com:5000/team/app:1.2.3est valide (port puis tag).team/app:5000est aussi valide (tag = 5000).registry.example.com:team/app:1.2.3n’est pas valide (le port doit être numérique).
Quand vous voyez « invalid reference format » et qu’un deux-points est impliqué, cherchez le cas des « deux deux-points » et confirmez lequel doit être le port.
Digests : images épinglées, syntaxe différente
Les digests ressemblent à @sha256:<hex>. Ils sont excellents pour la reproductibilité et terribles pour les humains. Si vous les générez dans des pipelines, assurez-vous de ne pas introduire d’espaces ni de troncature. Un caractère manquant change un pin en erreur de parsing.
Une citation que les personnes ops appliquent réellement
L’espérance n’est pas une stratégie.
— General Gordon R. Sullivan
C’est l’état d’esprit ici. Ne « espérez » pas que votre tag soit valide. Validez-le. Normalisez-le. Et échouez tôt avec votre propre message avant que le parseur Docker ne vous envoie dans un fil de tickets.
Faits intéressants et contexte historique (parce que les règles ne datent pas d’hier)
Ce sont des détails mineurs, mais ils expliquent pourquoi les règles de nommage semblent étrangement strictes et pourquoi la même erreur apparaît dans différents outils.
- Le nommage d’images précède la popularité actuelle de Docker. Les règles ont évolué avec les premières implémentations de registres qui avaient besoin de chemins déterministes et d’un comportement de cache.
- Le nommage en minuscules est en partie un pari de compatibilité. Les systèmes de fichiers insensibles à la casse (et les humains) rendent les noms en casse mixte problématiques, donc l’écosystème favorise les minuscules.
- Le parseur de « référence » est partagé. Beaucoup d’outils reposent sur la même logique de parsing sous-jacente, donc « invalid reference format » apparaît dans Docker, Compose et d’autres outils pour les mêmes causes racines.
- Les tags devaient être des labels légers, pas des dumps de métadonnées. Les gens entassent encore les noms de branches, timestamps et contexte de build dans des tags, puis sont surpris par les limites de caractères ou les séparateurs illégaux.
- Les digests existent pour résoudre la dérive du « latest ». La syntaxe du digest a gagné en importance quand les équipes ont réalisé que les tags peuvent être déplacés et que « latest » est un piège déguisé.
- La syntaxe hôte-de-registre + port a été empruntée aux conventions d’URL. L’ambiguïté du deux-points (port vs tag) est la taxe inévitable pour des références lisibles par l’humain.
- Docker Hub a influencé les valeurs par défaut de nommage. L’hypothèse de
library/pour les images officielles et des registres par défaut a façonné la manière d’écrire des noms courts commenginx. - Compose a amplifié le problème. YAML introduit des guillemets, des espaces et des interpolations de variables—excellent pour la config, excellent pour cacher les fautes de frappe.
- Les pipelines CI ont rendu les tags plus dynamiques. Une fois que les tags deviennent des fonctions de variables d’environnement, les échecs liés aux chaînes vides deviennent quotidiens.
Mode d’intervention rapide
Voici l’ordre que j’utilise quand on me réveille. Il est optimisé pour « trouver le goulot vite », pas pour l’élégance.
Premier point : capturez la chaîne exacte que Docker analyse
- Copiez la commande complète telle qu’exécutée, pas ce que vous pensez avoir lancé.
- Si c’est en CI, affichez la commande après expansion des variables (de façon sécurisée) ou echo la référence d’image calculée seule.
- Cherchez les espaces, retours à la ligne et caractères invisibles.
Second point : identifiez quel token est la référence d’image
- Dans
docker run, c’est le premier argument non-flag après les options. - Dans
docker build, c’est généralement la valeur de-t. - Dans Compose, c’est sous
image:ou dérivé debuild:+ nom de projet.
Troisième point : réduisez à un reproducer minimal
- Remplacez les variables par des valeurs littérales.
- Supprimez tout sauf la référence d’image.
- Essayez
docker image inspectoudocker pullsur la même référence. Si le parsing échoue, vous l’avez isolé.
Quatrième point : vérifiez ces coupables principaux dans l’ordre
- Caractères majuscules dans le chemin du dépôt.
- Le tag contient un slash (
/) ou un espace. - La référence se termine par
:(tag vide). - Séparateurs doubles :
//,@@,::au mauvais endroit. - Confusion hôte:port du registre (port non numérique, slash manquant après l’hôte).
- Problèmes de quoting du shell et de continuation de ligne.
Si vous ne faites qu’une chose : imprimez la référence d’image avec un outil qui révèle les caractères invisibles. La plupart des cas « mystère » se règlent immédiatement.
Tâches pratiques : commandes, sorties et décisions (12+)
Ceux-ci sont éprouvés sur le terrain. Chaque tâche inclut : une commande, ce que signifie la sortie, et la décision à prendre. Exécutez-les localement ou sur le runner CI qui échoue. Servez-vous-en pour transformer un message d’erreur vague en correction concrète.
Task 1: Reproduce parsing failure with docker pull
cr0x@server:~$ docker pull 'MyTeam/MyApp:1.0.0'
invalid reference format
Ce que cela signifie : Docker a rejeté la référence avant tout contact avec un registre. Les lettres majuscules dans le chemin du dépôt sont un déclencheur courant.
Décision : Normalisez les noms de dépôt en minuscules dans vos scripts de build/publish (myteam/myapp:1.0.0).
Task 2: Reveal hidden whitespace in a computed image string
cr0x@server:~$ IMAGE_REF="registry.local/team/app:${TAG} "
cr0x@server:~$ printf '%q\n' "$IMAGE_REF"
registry.local/team/app:${TAG}\
Ce que cela signifie : L’espace terminal est réel. Docker le considère comme faisant partie de la référence et échouera à l’analyser.
Décision : Coupez ou assainissez les variables. Ne concaténez pas avec des entrées non fiables. Préférez printf à echo dans les scripts.
Task 3: Confirm a variable is empty (classic CI failure)
cr0x@server:~$ TAG=""
cr0x@server:~$ docker build -t "team/app:${TAG}" .
invalid reference format
Ce que cela signifie : Un tag vide a créé une référence illégale se terminant par :.
Décision : Échouez tôt : imposez ${TAG:?TAG must be set} ou utilisez par défaut un tag sûr comme dev.
Task 4: Show how branch names break tags
cr0x@server:~$ BRANCH="feature/new-ui"
cr0x@server:~$ docker tag alpine:3.20 "team/app:${BRANCH}"
Error parsing reference: "team/app:feature/new-ui" is not a valid repository/tag: invalid reference format
Ce que cela signifie : Les tags ne peuvent pas contenir de slash. Les branches Git en contiennent souvent.
Décision : Sanitizez les noms de branche (remplacez / par -, supprimez les caractères illégaux) avant de créer un tag.
Task 5: Validate your sanitization in-shell
cr0x@server:~$ BRANCH="feature/new-ui"
cr0x@server:~$ SAFE_TAG="$(printf '%s' "$BRANCH" | tr '[:upper:]' '[:lower:]' | sed 's#[^a-z0-9_.-]#-#g')"
cr0x@server:~$ printf '%s\n' "$SAFE_TAG"
feature-new-ui
Ce que cela signifie : Vous avez transformé un tag invalide en un tag valide en apparence.
Décision : Utilisez une fonction/bibliothèque partagée pour la sanitisation des tags dans tous les pipelines. Ne la réécrivez pas différemment dans chaque repo.
Task 6: Catch Windows CRLF contamination (yes, it happens)
cr0x@server:~$ TAG="$(printf '1.2.3\r')"
cr0x@server:~$ printf '%q\n' "$TAG"
$'1.2.3\r'
Ce que cela signifie : Il y a un retour chariot dans le tag. Docker peut lancer « invalid reference format » ou se comporter de manière incohérente selon l’endroit où il apparaît.
Décision : Supprimez \r des variables et fichiers CI : assainissez les entrées provenant de Git, des outils de release et des étapes Windows.
Task 7: Distinguish registry port vs tag colon usage
cr0x@server:~$ docker pull registry.local:5000/team/app:1.2.3
Error response from daemon: manifest for registry.local:5000/team/app:1.2.3 not found: manifest unknown
Ce que cela signifie : La référence a été analysée avec succès. Vous êtes passé du formatage au contenu/registre (manifest not found).
Décision : Arrêtez de chercher une faute de format. Vérifiez si le tag existe dans le registre.
Task 8: Trigger the “non-numeric port” failure mode
cr0x@server:~$ docker pull registry.local:five000/team/app:1.2.3
invalid reference format
Ce que cela signifie : Docker a essayé d’analyser registry.local:five000 comme host:port et l’a rejeté parce que le port n’est pas numérique.
Décision : Auditez le templating qui assemble les noms d’hôtes de registre. N’interpolez pas des « noms d’environnement » là où un port est attendu.
Task 9: Confirm the image reference token position in docker run
cr0x@server:~$ docker run --rm -e FOO=bar 'team/app:1.0.0 '
Unable to find image 'team/app:1.0.0 ' locally
invalid reference format
Ce que cela signifie : La référence incluait un espace terminal. Docker l’affiche tel quel, puis échoue au parsing/pull.
Décision : Arrêtez de copier des commandes depuis des docs/chats formatés sans retaper le dernier caractère. Aussi : quotez les variables, pas des chaînes composées avec des espaces inconnus.
Task 10: Use docker image inspect to separate “format” from “doesn’t exist”
cr0x@server:~$ docker image inspect team/app:1.0.0
[]
Error: No such image: team/app:1.0.0
Ce que cela signifie : La référence est valide, mais l’image n’est pas présente localement.
Décision : Si vous l’attendiez localement, corrigez les étapes de build/pull. Sinon, lancez docker pull et vérifiez le registre.
Task 11: Confirm Compose interpolation produced what you think
cr0x@server:~$ cat docker-compose.yml
services:
api:
image: "registry.local/team/api:${TAG}"
cr0x@server:~$ TAG= docker compose config
services:
api:
image: registry.local/team/api:
Ce que cela signifie : Compose a rendu l’image avec un tag vide. Ce deux-points terminal explosera plus tard en « invalid reference format » ou lors du pull/run.
Décision : Utilisez l’expansion par défaut dans Compose : ${TAG:-dev} ou imposez la présence des vars en CI avant d’appeler Compose.
Task 12: Catch YAML quoting and newline accidents
cr0x@server:~$ python3 - <<'PY'
import os
ref = "registry.local/team/app:1.2.3\n"
print(repr(ref))
PY
'registry.local/team/app:1.2.3\n'
Ce que cela signifie : Des retours à la ligne peuvent s’infiltrer quand les chaînes proviennent de fichiers, de templates ou de scalaires YAML en bloc.
Décision : Utilisez des chaînes YAML sur une seule ligne pour les références d’image. Évitez les scalaires en bloc pour tout ce qui devient un token en ligne de commande.
Task 13: Confirm your shell didn’t split the reference
cr0x@server:~$ REF="team/app:1.0.0"
cr0x@server:~$ set -x
cr0x@server:~$ docker run --rm $REF
+ docker run --rm team/app:1.0.0
Unable to find image 'team/app:1.0.0' locally
docker: Error response from daemon: pull access denied for team/app, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
See 'docker run --help'.
Ce que cela signifie : Ce n’est pas une erreur de format ; c’est une question d’authentification/registre/disponibilité.
Décision : Cessez de déboguer la syntaxe. Déboguez les identifiants, les permissions du registre, ou le chemin correct du dépôt.
Task 14: Validate a digest reference separately from a tag
cr0x@server:~$ docker pull alpine@sha256:deadbeef
invalid reference format
Ce que cela signifie : Le digest est malformé (trop court, non-hex, etc.). Docker le rejette dès l’analyse de la référence.
Décision : Ne tapez pas les digests à la main. Copiez exactement, et faites vérifier la longueur/le format du digest avant de l’utiliser.
Petite blague #2 : Un espace terminal dans un tag d’image, c’est comme des paillettes à la maison : vous ne les voyez pas, mais elles gâchent votre soirée.
Trois mini-histoires du monde de l’entreprise
Mini-histoire 1 : L’incident causé par une fausse hypothèse
L’équipe s’était mise d’accord sur des « tags de branche » pour les environnements de prévisualisation. Les branches de fonctionnalité étaient intégrées dans des images, déployées dans des namespaces éphémères. Tout le monde aimait ça — jusqu’à un jeudi après-midi où les déploiements de preview ont commencé à échouer sur plusieurs repos.
Le responsable de garde l’a d’abord traité comme une panne de registre. L’erreur dans les logs : « invalid reference format. » Ce message attire le mauvais type de débogage, parce qu’il apparaît à côté des pulls et des runs. Ils ont vérifié la santé du registre, les chemins réseau, le DNS et les tokens d’auth. Tout semblait normal. Les builds poussaient encore quelque chose pour certains services, mais pas pour d’autres.
La mauvaise hypothèse : « Si ça échoue pendant le déploiement, ça doit être un problème du système de déploiement. » En réalité, le déploiement était le premier endroit où le mauvais tag devenait visible. Le changement déclencheur était une mise à jour de politique du repo : les noms de branches ont commencé à inclure des préfixes en majuscules pour les types de travail. Pensez à Feature/New-UI ou Hotfix/.... Git l’accepte. Les humains l’acceptent. Les tags Docker n’acceptent pas le slash, et les chemins de dépôt n’acceptent pas les majuscules dans de nombreux contextes.
Le diagnostic a enfin cliqué quand quelqu’un a imprimé la référence d’image calculée avec échappement visible et a vu team/api:Feature/New-UI. La correction était ennuyeuse : sanitiser le nom de branche en un tag sûr et imposer les minuscules. Ils ont aussi ajouté un garde-fou pour que le pipeline échoue avec un message clair avant d’invoquer Docker.
La leçon du postmortem n’était pas sur Docker. C’était sur les hypothèses. Les systèmes échouent là où les contraintes rencontrent la réalité. Le nommage des branches Git a des contraintes différentes des tags d’images, et « ça marchait la semaine dernière » n’est pas un contrat.
Mini-histoire 2 : L’optimisation qui s’est retournée contre eux
Une équipe plateforme a décidé d’accélérer la CI en générant des tags d’image à partir du ref Git complet, plus un SHA court, plus un timestamp de build. Le but : traçabilité sans lookup. Sur le papier : parfait. Dans les pipelines : une comédie à petits pas.
L’optimisation a été implémentée comme une petite fonction shell réutilisée dans les repos. Elle utilisait echo à tout va, passait par quelques utilitaires texte, et finissait par une newline. Cette newline n’importait pas pour les logs. Elle importait beaucoup une fois interpolée dans docker build -t. Certains runners la supprimaient, d’autres non. Sur certains shells, elle devenait un espace terminal ou un saut de ligne littéral selon la façon dont les variables étaient développées.
La plupart des builds passaient. Puis un sous-ensemble a commencé à échouer avec « invalid reference format », apparemment au hasard. Les développeurs ont blâmé les versions Docker, les images runners, et la CI « flaky ». Le responsable de garde a blâmé la lune.
La cause racine s’est avérée être le tag de traçabilité qui dépassait parfois les contraintes et souvent contenait des caractères illégaux copiés depuis le format de ref Git. Le format timestamp incluait aussi des deux-points, légaux dans certains contextes mais risqués combinés à d’autres étapes de parsing et de formatage de logs. La newline a été l’insulte finale.
Le rollback a été immédiat. Le remplacement plus simple : les tags sont devenus ${sanitized_branch}-${short_sha} avec des caps strictes de longueur, et les métadonnées riches sont passées dans des labels (org.opencontainers.image.revision, org.opencontainers.image.source) là où elles avaient leur place. La traçabilité s’est améliorée. La CI a arrêté de « casser aléatoirement ».
Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une autre organisation avait une habitude apparemment trop prudente : chaque étape de pipeline qui calculait une référence d’image l’écrivait dans un fichier, la validait avec un petit script, puis l’affichait avec un formatage ami des échappements. Personne n’adorait ces lignes de code supplémentaires. Mais c’était cohérent, testé et partagé.
Un jour, un nouveau service a été ajouté par une équipe qui travaillait surtout avec des outils Windows. Leur pipeline a injecté une chaîne de version lue depuis un fichier qui contenait des fins de ligne CRLF. Le tag semblait correct dans les logs. Mais la chaîne calculée contenait un \r caché. Docker a commencé à lancer « invalid reference format ».
C’est là que la pratique ennuyeuse a payé : le script validateur a signalé que le tag contenait un retour chariot et a échoué tôt avec un message indiquant la valeur d’octet exacte et le fichier d’origine. Pas de debugging de registre. Pas de trous de lapin Compose. Pas de « ça marche sur ma machine ».
La correction a été une étape de normalisation d’une ligne dans le pipeline et une politique de repo pour s’assurer que les fichiers de version sont en LF. Cela n’a jamais été une panne. C’est devenu un ticket clos avec une cause racine claire et un système durci.
La bonne opération consiste souvent à refuser que des chaînes ambigües traversent vos systèmes sans contrôle. Ce n’est pas glamour. C’est efficace.
Erreurs fréquentes : symptôme → cause racine → correction
Cette section est conçue pour être utilisée quand vous regardez des logs. Chaque entrée relie un symptôme reconnaissable à la cause la plus probable et à une correction spécifique.
1) Symptom: “invalid reference format” when using docker build -t
Cause racine : La variable de tag est vide ou contient des espaces/retours à la ligne.
Correction : Imposer les variables requises et couper les entrées. Utilisez ${TAG:?TAG must be set} et générez les tags avec printf plutôt qu’avec echo.
2) Symptom: Works locally, fails in CI with the same-looking command
Cause racine : Les variables CI contiennent des caractères invisibles (\r, espace terminal) ou sont interpolées différemment par le shell.
Correction : Affichez la référence calculée avec printf '%q\n'. Normalisez les fins de ligne et utilisez des options shell strictes (set -euo pipefail).
3) Symptom: “Error parsing reference … is not a valid repository/tag”
Cause racine : Le tag contient / (nom de branche) ou le dépôt contient des majuscules.
Correction : Sanitizez les noms de branche en tags ; forcez les minuscules pour les chemins de dépôt.
4) Symptom: Invalid reference format with a registry hostname + port
Cause racine : Port non numérique, slash manquant après l’hôte, ou deux-points accidentel en trop.
Correction : Assurez-vous de host:port/path/name:tag. Séparez la construction de l’hôte de registre de celle du tag.
5) Symptom: Fails only when copying from chat or tickets
Cause racine : Guillemets « intelligents », espaces insécables, ou ponctuation Unicode.
Correction : Retapez les guillemets manuellement ; validez avec python3 en affichant repr() ou avec printf '%q' du shell.
6) Symptom: Compose says invalid reference format, but YAML looks fine
Cause racine : L’expansion de variable a créé un tag vide, ou un scalaire YAML en bloc a introduit un saut de ligne.
Correction : Lancez docker compose config et inspectez la sortie rendue. Utilisez ${VAR:-default} ou imposez la présence des variables.
7) Symptom: You tried to use a digest, and it fails immediately
Cause racine : Le digest est malformé ou tronqué.
Correction : Copiez le digest complet ; ajoutez des vérifications pour le préfixe attendu sha256: et la longueur avant usage.
8) Symptom: The error appears after you “optimized” tagging for traceability
Cause racine : Le tag inclut des caractères illégaux ou devient trop long ; les métadonnées sont entassées dans les tags.
Correction : Mettez les métadonnées dans des labels OCI. Gardez les tags courts, nettoyés et stables.
9) Symptom: Reference looks valid but Docker still complains
Cause racine : Espaces invisibles, surtout espace terminal ou saut de ligne.
Correction : Affichez avec échappement et vérifiez le contenu octet par octet. Traitez toutes les chaînes comme hostiles jusqu’à preuve du contraire.
Listes de contrôle / plan étape par étape
Checklist A: When you see “invalid reference format” in an incident
- Extrait la chaîne exacte de la référence depuis les logs ou la sortie de l’étape CI. Ne la retapez pas encore.
- Révélez les invisibles : affichez avec échappement (
printf '%q\n') ou représentation (python3 -cavecrepr). - Confirmez quel outil l’a produite (CLI Docker, Compose, système de build). Trouvez l’endroit où la référence est assemblée.
- Vérifiez les variables pour vide et les valeurs par défaut. Les chaînes vides sont la cause n°1 du deux-points final.
- Scannez les caractères illégaux : espaces, slashs dans les tags, majuscules dans le chemin,
\r. - Réduisez à un reproducer minimal :
docker pulloudocker image inspectavec la référence exacte. - Corrigez à la source : l’étape de construction de la chaîne, pas l’invocation Docker.
- Ajoutez une validation préflight qui échoue avec un message humain avant Docker.
Checklist B: A robust way to generate tags in CI
- Choisissez les entrées : nom de branche, SHA court, numéro de build optionnel.
- Tout mettre en minuscules (les tags peuvent être en casse mixte parfois, mais la cohérence prime).
- Remplacez les caractères illégaux par
-. - Réduisez les séparateurs répétés (évitez le bazar
---). - Coupez les séparateurs en début/fin.
- Imposez une longueur maximale (choisissez une limite sensée comme 60–80 caractères pour éviter les cas limites).
- Émettez avec
printfsans surprises de newline. - Stockez la référence calculée dans un fichier artifact et réutilisez-la de façon cohérente.
Checklist C: Prevention controls I actually recommend
- Une bibliothèque de tagging partagée par organisation (fonction shell, target Make, petit helper Go/Python). Pas de logique bespoke par repo.
- Vérifications fail-fast des variables avant d’appeler Docker ou Compose.
- Rendu Compose enregistré comme artifact CI pour le debugging (
docker compose config). - Labels OCI pour les métadonnées, pas l’inflation des tags.
- Linting des références d’image en CI (même une règle regex vaut mieux que l’impression).
FAQ
1) Does “invalid reference format” ever mean the registry is down?
Presque jamais. En général, ça échoue avant tout appel réseau. Si vous voyez cela, pensez d’abord au parsing de la chaîne. Si la référence est analysée, vous obtiendrez des erreurs comme « manifest unknown », « pull access denied » ou des échecs TLS/auth.
2) Why does Docker hate uppercase letters?
C’est pour la cohérence et la compatibilité entre systèmes de fichiers, registres et outils. Les dépôts en casse mixte créent de l’ambiguïté et des problèmes opérationnels. L’écosystème a choisi la rigueur plutôt que le chaos.
3) Can a Docker tag contain a slash?
Non. Un slash est un séparateur de chemin dans le nom du dépôt. Si vous essayez de mettre une branche Git comme feature/foo dans un tag, vous obtiendrez des échecs de parsing. Sanitizez d’abord.
4) What’s the difference between a tag and a digest in practice?
Un tag est un pointeur mutable (il peut être déplacé vers une autre image). Un digest est une adresse de contenu et est pratiquement immuable. Utilisez les digests pour la reproductibilité, les tags pour les workflows et la navigation humaine.
5) Compose shows the error, but the image line looks correct. Now what?
Exécutez docker compose config. Compose peut interpoler des variables en un tag vide ou insérer des espaces/sauts de ligne via le YAML. Déboguez la config rendue, pas le YAML source.
6) Why did it work yesterday and fail today with the same pipeline?
Parce que les entrées ont changé : noms de branches, chaînes de version, variables d’environnement, OS du runner, ou fins de ligne. Votre pipeline est une usine à chaînes. Tout nouveau caractère peut déclencher un incident en production.
7) How do I safely print a reference for debugging without leaking secrets?
Les références d’image ne devraient pas contenir de secrets. Si les vôtres en contiennent (par exemple en embarquant des identifiants dans la chaîne du registre), arrêtez et corrigez cette architecture. Pour le debugging, affichez uniquement la référence calculée et conservez les identifiants avec docker login ou des helpers d’identifiants.
8) Is “latest” related to this error?
Pas directement. latest est un tag valide. Il pose juste d’autres problèmes (dérive, déploiements surprises). Utilisez des tags explicites ou des digests et réservez latest au développement local si nécessaire.
9) What’s the quickest way to prove it’s whitespace?
Dans un shell : printf '%q\n' "$REF". En Python : print repr(REF). Si vous voyez \r, \n, ou un espace échappé à la fin, vous avez trouvé le coupable.
Conclusion : actions pour éviter la récidive
« invalid reference format » est une plainte du parseur, pas une affirmation philosophique. Traitez-la comme une URL malformée : isolez la chaîne exacte, révélez les caractères cachés, validez les entrées, et cessez de laisser du texte libre façonner le comportement en production.
Actions concrètes que je mettrais en place cette semaine :
- Ajoutez une étape préflight dans chaque pipeline CI qui affiche la référence d’image calculée avec échappement et échoue si elle contient des caractères illégaux ou est vide.
- Standardisez la génération de tags dans un helper partagé, avec sanitisation, limites de longueur et minuscules constantes.
- Déplacez les métadonnées dans des labels OCI au lieu de tags gonflés qui finissent par heurter des cas limites.
- Rendez visible le rendu Compose : stockez la sortie
docker compose configcomme artifact pour chaque job de déploiement.
La correction est rarement complexe. La discipline l’est. La bonne nouvelle : une fois que vous cessez de traiter les références d’image comme des chaînes occasionnelles, ce gaspilleur d’heures disparaît pour la plupart. Et vous retrouvez quelques heures que Docker vous volait en catimini.