Image Docker MinIO introuvable : la reconstruire
Denis PEYRUSAUBES
J’avais été prévenu. Le 8 juin 2025, l’éditeur annonçait le lancement d’AIStor et son recentrage sur les usages IA/ML. Quelques jours plus tôt, il avait déjà distingué MinIO Object Store, l’offre communautaire, d’AIStor, l’offre commerciale (présentation officielle du 29 mai). J’en avais retenu qu’il était prudent de préparer une sortie de l’édition communautaire. Puis j’ai repoussé la migration de mois en mois : une alerte précoce peut aussi devenir une excellente raison de remettre le sujet à plus tard. MinIO situe aujourd’hui la fin de vie de ses produits open source en septembre 2025 (centre juridique). Quinze mois après l’annonce, le 26 septembre 2026, des nœuds neufs sortis d’hibernation, sans image en cache, ont transformé cette échéance différée en urgence : l’image MinIO était introuvable et le pod restait en ImagePullBackOff.
J’ai donc reconstruit MinIO depuis le dernier tag source que j’utilisais, puis publié l’image dans mon registre privé Amazon ECR. C’était un dépannage pour redémarrer sans changer en même temps le serveur de stockage et ses données, pas une manière de relancer le projet ni une solution durable.
Quand l’image devient une dépendance de production
MinIO fournissait l’API S3 partagée par neuf outils de la plateforme. Quand le pod ne pouvait pas démarrer, Tempo, plusieurs composants de Mimir, le backend de Loki et le registre de conteneurs GitLab étaient à leur tour indisponibles. Le problème initial était une image manquante, mais son rayon d’impact était celui d’une panne de stockage central.
J’ai d’abord vérifié les sources d’images disponibles. Ce soir-là, mes essais n’ont pas permis de récupérer l’image exacte depuis les registres attendus ; le téléchargement du binaire historique échouait également. Ce constat décrit l’incident et les références testées, pas une règle éternelle sur tous les miroirs. Le dépôt officiel de MinIO a depuis été archivé et est en lecture seule : reconstruire le logiciel ne rétablit donc pas sa maintenance amont.
Une image Bitnami de la même période semblait être une issue possible. Mais elle n’était pas un remplacement transparent : le chart MinIO en place attendait des chemins, un point d’entrée et un binaire conformes à l’image officielle. Substituer l’image aurait impliqué d’adapter et de tester le chart pendant l’incident, avec un stockage S3 dont dépendaient déjà de nombreux services. J’ai préféré reconstruire le format attendu par le déploiement existant et repousser le changement de serveur à une migration séparée.
Reconstruire une version identifiable, pas « MinIO » en général
J’ai retenu le tag RELEASE.2024-12-18T13-15-44Z et contrôlé qu’il correspondait au commit 16f8cf1c52f0a77eeb8f7565aaf7f7df12454583. Le clonage était limité à ce tag, puis le commit récupéré était comparé à cette valeur connue. Cette vérification ferme la porte à une référence qui aurait été déplacée : le build doit s’arrêter si le code n’est pas celui attendu.
Cette précision est essentielle pour un logiciel serveur. Une étiquette lisible comme « dernière version » ne suffit pas à expliquer quel code a produit un binaire. Ici, le tag décrit la version amont et le hash identifie exactement le commit. La procédure peut ainsi être répétée et auditée, même si elle ne remplace pas une chaîne de publication officielle maintenue.
Le Dockerfile reprend l’approche multi-étape du projet. La première étape compile le code Go dans une image de construction, puis l’étape finale copie le binaire et les fichiers nécessaires dans une base minimale compatible avec les attentes de l’image officielle. On évite ainsi d’embarquer compilateur et dépendances de build dans l’image exécutée en production.
Un détail a eu un effet visible : avant l’appel au générateur amont buildscripts/gen-ldflags.go, il faut définir MINIO_RELEASE=RELEASE. Sans cette valeur, le binaire se présentait comme une version de développement, malgré une compilation issue du bon tag. Le tag du dépôt, les métadonnées injectées au build et le résultat de minio --version doivent raconter la même histoire.
L’image finale conserve les conventions attendues par le chart : le binaire dans /usr/bin/minio, le script docker-entrypoint.sh au chemin prévu, le volume /data et le port 9000. J’ai également gardé les fichiers de licence et de crédits dans l’image. Avant toute redistribution, les obligations de la licence du logiciel doivent être vérifiées ; la présence des fichiers est une précaution, pas un avis juridique.
Construire sur un Mac pour une plateforme amd64
Mon poste de travail est un Mac Apple Silicon, tandis que les nœuds EKS de cette plateforme attendent linux/amd64. La compilation Go peut cibler cette architecture sans exécuter le binaire dans une machine émulée : l’étape de build utilise la plateforme native du constructeur, puis reçoit TARGETOS et TARGETARCH comme paramètres de compilation.
Cette distinction évite une confusion fréquente : la plateforme du constructeur n’est pas nécessairement celle de l’image finale. Le résultat a été contrôlé avec minio --version, puis en vérifiant l’architecture ELF du binaire (x86_64). La documentation Docker décrit ce mécanisme de compilation croisée avec BUILDPLATFORM, TARGETOS et TARGETARCH dans son guide sur les builds multi-plateformes.
Le message Buildx qui mentionnait linux/arm64 m’a d’abord fait douter de la cible. Mais il concernait le constructeur ou le démon utilisé ; il ne prouvait pas à lui seul l’architecture de l’image publiée. C’est l’inspection du binaire livré, et son démarrage sur la plateforme cible, qui tranche.
Publier dans ECR et traiter aussi le client mc
J’ai créé des dépôts ECR dédiés à minio et mc, avec des tags immuables, l’analyse d’image à la publication et une rétention limitée aux cinq dernières images. Le tag de MinIO reprend la release exacte ; je n’ai pas ajouté de tag flottant latest. Avec l’immutabilité ECR, un tag existant ne peut pas être écrasé par une autre image, ce qui rend les références de déploiement plus prévisibles (documentation AWS).
Le serveur n’était pas le seul consommateur d’une image devenue indisponible. Les jobs d’initialisation de buckets utilisaient minio/mc:latest, le client en ligne de commande. Je l’ai donc reconstruit séparément depuis son propre tag et son commit vérifié. Les neuf jobs GitOps ont été repointés vers cette image privée et versionnée. Comme les objets Job Kubernetes sont immuables sur plusieurs champs, les changements ont nécessité leur remplacement déclaratif plutôt qu’une simple mise à jour en place.
Cette séparation est importante : serveur et client ont leurs propres versions, exécutables et cycles d’usage. Le fait d’avoir compilé minio ne fournit pas automatiquement un mc compatible. Il faut vérifier chacun des artefacts réellement référencés par les manifests et les jobs.
Vérifier le retour, puis documenter la dette
J’ai redémarré MinIO sur le volume persistant existant, en conservant la version et le format des données. Après publication et mise à jour du chart, les applications sont revenues à l’état Synced/Healthy dans Argo CD. Les neuf jobs de création des buckets ont ensuite terminé avec succès. Aucun déplacement de données n’était nécessaire pour cette remise en service.
Le succès du redémarrage ne rend pas cette image équivalente à un produit maintenu. Elle reste fondée sur une version de décembre 2024 ; elle ne recevra pas automatiquement les futurs correctifs, et c’est désormais à moi d’en assumer la construction, la conservation et la vérification. Il faut aussi refaire périodiquement les tests de restauration et de démarrage à froid : tant qu’une image est en cache, une dépendance de registre cassée peut rester invisible.
Cette reconstruction a été le premier volet de l’histoire, pas sa conclusion. Elle a permis de redémarrer sans toucher aux objets, mais pas de faire disparaître la dette de maintenance. La migration vers SeaweedFS est désormais achevée : neuf outils ont été basculés après copie et validation de leurs données. Le récit compagnon revient sur les essais, le choix de SeaweedFS et les compromis rencontrés : migrer de MinIO vers SeaweedFS.
Le 3 octobre, j’ai également publié les images reconstruites sur Docker Hub sous retengr/minio-rebuild et retengr/mc-rebuild, en complément des dépôts privés ECR. Les images publiques facilitent leur réutilisation, mais ne changent ni leur provenance ni leur statut : elles sont construites à partir de versions anciennes, sans maintenance amont. Leur publication ne remplace donc pas la migration ni les précautions de licence et de sécurité.
Tout ce que cet incident a mobilisé relève du socle : savoir d’où vient une image, l’épingler par son empreinte plutôt que par une étiquette flottante, la reconstruire depuis la source et la pousser dans un registre qu’on maîtrise. C’est ce que couvre notre formation Docker, où la construction d’images et la gestion des registres occupent une large place.