Créer un namespace de registre prend moins d'une seconde, et pousser une image de 3 Mo en prend trois. Cette leçon publie une image sur Container Registry, puis répond à la seule question qui compte vraiment : qui peut la tirer ? Vous découvrirez que la visibilité se règle par image et surclasse celle du namespace, qu'un cluster Kapsule n'a pas besoin du secret de tirage que la documentation officielle présente comme obligatoire, et que le champ size de l'API ne mesure pas ce que vous croyez. Chaque droit d'accès est prouvé, jamais supposé.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Publier une image et mesurer ce que coûte chaque envoi suivant.
- Distinguer la visibilité du namespace de celle de chaque image.
- Prouver un droit d'accès au lieu de le déduire d'un code de retour.
- Décider quand un
imagePullSecretest nécessaire, et quand il ne l'est pas.
Prérequis
Section intitulée « Prérequis »- Un compte Scaleway avec un projet dédié et un profil
scwisolé. dockeroupodmanen local, etjqpour lire les sorties JSON.- Pour la dernière partie, un cluster Kapsule : voir créer un cluster Kapsule.
Comment créer un namespace et y pousser une image ?
Section intitulée « Comment créer un namespace et y pousser une image ? »Un namespace est le conteneur de vos images, et son nom est unique. C'est la première contrainte à connaître, parce qu'elle se découvre par un refus.
-
Créer le namespace, en privé, qui est le réglage à enseigner.
Fenêtre de terminal NS_ID=$(scw registry namespace create \name=demo-registre-$(date +%s) \region=fr-par \is-public=false \-o json | jq -r '.id')ENDPOINT=$(scw registry namespace get "${NS_ID}" region=fr-par -o json | jq -r '.endpoint')echo "endpoint : ${ENDPOINT}"La sortie doit afficher une adresse en
rg.fr-par.scw.cloud/. Mesuré le 2026-09-12 : moins d'une seconde, le namespace estreadyimmédiatement. -
Se connecter au registre. La commande pose les identifiants dans votre client local.
Fenêtre de terminal scw registry login region=fr-parLa sortie doit afficher
Login Succeeded. L'argumentprogramacceptedockeroupodman. -
Construire une image et la pousser.
Fenêtre de terminal cat > Dockerfile <<'DOCKERFILE'FROM alpine:3.22@sha256:14358309a308569c32bdc37e2e0e9694be33a9d99e68afb0f5ff33cc1f695dceRUN echo "demo scaleway" > /etc/demo-markerCMD ["cat", "/etc/demo-marker"]DOCKERFILEdocker build -t "${ENDPOINT}/demo:1.0.0" .docker push "${ENDPOINT}/demo:1.0.0"La sortie doit finir par une ligne
1.0.0: digest: sha256:… size: …. Mesuré : 3 secondes pour une image Alpine de 3 Mo. -
Vérifier côté API que l'image est bien référencée.
Fenêtre de terminal scw registry image list namespace-id="${NS_ID}" region=fr-par -o json \| jq -r '.[] | "image \(.name) : visibilité \(.visibility), \(.tags | length) tag(s)"'La sortie doit afficher
visibilité inherit. Retenez ce mot, la section suivante en dépend.
Que coûte réellement un second envoi de la même image ?
Section intitulée « Que coûte réellement un second envoi de la même image ? »Presque rien, parce que le registre déduplique par couche. C'est mesurable en trois commandes, et cela change la façon de construire vos images.
docker tag "${ENDPOINT}/demo:1.0.0" "${ENDPOINT}/demo:1.0.1"docker push "${ENDPOINT}/demo:1.0.1"La sortie doit afficher Layer already exists sur chaque couche. Mesuré le 2026-09-12 : 1 seconde, contre 3 pour l'envoi initial, et aucune couche ne remonte.
La conséquence pratique dépasse le registre. Si vos couches sont stables, republier coûte une seconde et zéro octet de stockage supplémentaire, puisque deux tags qui pointent le même contenu partagent le même digest. À l'inverse, une instruction qui invalide le cache tôt dans le Dockerfile, comme un COPY . . placé avant l'installation des dépendances, fait remonter toutes les couches suivantes à chaque build. Le registre ne fait que révéler le défaut : il est dans l'ordre de vos instructions.
Qui peut tirer votre image ?
Section intitulée « Qui peut tirer votre image ? »La visibilité se règle par image, et elle surclasse celle du namespace. C'est le point le plus important de cette leçon, parce qu'une seule image mal réglée expose son contenu à Internet entier sans que le namespace change d'apparence.
| Valeur | Effet | Quand la choisir |
|---|---|---|
inherit | suit le namespace | défaut d'une image poussée, sain tant que le namespace est privé |
private | authentification exigée | images applicatives, toujours |
public | tirage anonyme autorisé | images destinées à être distribuées, et elles seules |
Ne déduisez pas ce réglage d'un essai naïf. Un docker pull sur une image encore présente en cache local répond Status: Image is up to date sans rien télécharger, et ne démontre donc aucun droit d'accès. Il faut forcer un vrai transfert :
IMAGE_ID=$(scw registry image list namespace-id="${NS_ID}" region=fr-par -o json | jq -r '.[0].id')
essayer_tirage() { docker rmi -f "${ENDPOINT}/demo:1.0.0" > /dev/null 2>&1 || true # forcer le téléchargement docker logout "${ENDPOINT%%/*}" > /dev/null 2>&1 || true docker pull "${ENDPOINT}/demo:1.0.0" 2>&1 | tail -1}
scw registry image update "${IMAGE_ID}" region=fr-par visibility=private -o json | jq -r '.visibility'essayer_tirageLa sortie doit afficher le refus exact :
Error response from daemon: pull access denied for rg.fr-par.scw.cloud/…/demo,repository does not exist or may require 'docker login'Basculez maintenant une seule image en public, dans un namespace qui reste privé :
scw registry image update "${IMAGE_ID}" region=fr-par visibility=public -o json | jq -r '.visibility'sleep 5essayer_tirageLa sortie doit afficher une ligne Pull complete, preuve d'un téléchargement réel par un client non authentifié. Remettez ensuite l'image en private.
Un cluster Kapsule a-t-il besoin d'un secret de tirage ?
Section intitulée « Un cluster Kapsule a-t-il besoin d'un secret de tirage ? »Non, pas pour un registre du même projet, et c'est contraire à ce que la documentation officielle laisse entendre. Le guide Scaleway de déploiement depuis Container Registry présente la création d'un Image Pull Secret comme une étape nécessaire. Mesure faite le 2026-09-12 sur un cluster Kapsule 1.37.0 :
kubectl run essai-prive --image="${ENDPOINT}/demo:1.0.0" --restart=Never \ --command -- cat /etc/demo-markerkubectl get events --field-selector involvedObject.name=essai-prive \ -o custom-columns=RAISON:.reason,MESSAGE:.message --no-headersLa sortie doit afficher un tirage réussi :
Pulled Successfully pulled image "rg.fr-par.scw.cloud/…/demo:1.0.0" in 2.488s (16.593s including waiting). Image size: 3790331 bytes.Trois conditions ont été vérifiées avant d'en tirer une conclusion : le namespace était is_public: false, l'image visibility: private, et le cluster ne contenait aucun secret de registre, pas même sur le ServiceAccount par défaut.
Ce que cette mesure prouve exactement, et il faut s'y tenir : l'authentification au registre est assurée au niveau du nœud, en dehors des objets Kubernetes observables, et aucun imagePullSecret n'est nécessaire dans ce cas. Le mécanisme précis n'a pas été inspecté : identifiants statiques déposés à la création du nœud, fournisseur d'identifiants dynamique, ou autre. Conclure « des identifiants sont posés sur le nœud » irait au-delà de ce qui a été observé.
kubectl get serviceaccount default -o jsonpath='{.imagePullSecrets}'kubectl get secrets --all-namespaces | grep -i 'registry\|docker'Les deux sorties doivent être vides.
La portée de cette facilité mérite d'être comprise, parce qu'elle décide de ce qui marchera ailleurs. Ce que le lab établit, c'est que le nœud Kapsule sait s'authentifier auprès du Container Registry de son propre projet sans qu'aucun objet Kubernetes ne porte d'identifiant : ni Secret, ni imagePullSecrets sur le ServiceAccount. Le mécanisme vit donc au niveau du nœud ou de son runtime, et non dans le cluster. Sa forme exacte reste à inspecter, et ce guide ne la suppose pas. Deux conséquences en découlent, et elles vont dans des sens opposés. D'un côté, le déploiement d'images internes se simplifie : pas de secret à créer, à faire tourner, ni à répliquer dans chaque namespace. De l'autre, cette authentification est invisible dans vos manifestes, donc absente de toute revue de code, et elle disparaît silencieusement dès que l'image vient d'ailleurs. Un manifeste qui fonctionne sur votre cluster peut échouer sur celui d'une autre équipe, sans qu'aucune ligne n'ait changé.
Quand le secret de tirage redevient nécessaire
Section intitulée « Quand le secret de tirage redevient nécessaire »La documentation officielle n'est pas fausse, elle est inconditionnelle. Le secret reste indispensable dès que vous sortez du cas courant, et ce tableau dit lequel :
| Origine de l'image | Besoin d'un imagePullSecret | Pourquoi |
|---|---|---|
| Registre Scaleway, même projet | non | les identifiants sont déjà sur le nœud |
| Registre Scaleway, autre projet | oui | le nœud n'a pas de droit sur ce projet |
| Registre Scaleway, autre organisation | oui | idem, et la clé d'API diffère |
| Registre tiers, Docker Hub privé ou autre | oui | Scaleway ne pose aucun identifiant pour eux |
Ces trois lignes ne sont pas déduites, elles sont mesurées. Le 2026-09-12, un cluster du projet A a tenté de tirer une image privée d'un projet B de la même organisation, sans secret :
Failed to pull image "rg.fr-par.scw.cloud/…/demo:1.0.0": failed to resolve image:pull access denied, repository does not exist or may require authorization:server message: insufficient_scope: authorization failedinsufficient_scope est le mot qui compte : le nœud possède bien des identifiants, mais leur portée s'arrête au projet du cluster. Le pod reste en ImagePullBackOff indéfiniment.
Dans les trois derniers cas, le secret se crée ainsi, la clé d'API n'étant jamais écrite dans un fichier versionné :
kubectl create secret docker-registry registre-externe \ --docker-server=rg.fr-par.scw.cloud \ --docker-username=nologin \ --docker-password="${SCW_SECRET_KEY}"La sortie doit afficher secret/registre-externe created. Le secret doit vivre dans le même namespace que les pods qui l'utilisent, et se référence par imagePullSecrets dans la spécification du pod.
Où placer le registre par rapport au cluster ?
Section intitulée « Où placer le registre par rapport au cluster ? »Dans la même région, sinon chaque tirage devient du trafic facturé. C'est la seule décision d'architecture de cette leçon, et elle se prend à la création du namespace.
| Images stockées | Sortie inter-régionale | Sortie intra-régionale | Entrée | |
|---|---|---|---|---|
| Privées | 0,027 €/Go/mois | 0,033 €/Go | gratuite | gratuite |
| Publiques | gratuites jusqu'à 75 Go | gratuite | gratuite | gratuite |
Un cluster en fr-par qui tire depuis un namespace fr-par ne paie aucun transfert, seulement le stockage. Le même cluster tirant depuis nl-ams paie 0,033 €/Go à chaque tirage, ce qui, sur une flotte qui redémarre souvent, cesse vite d'être anecdotique.
Nettoyer
Section intitulée « Nettoyer »Supprimer le namespace emporte toutes ses images. C'est la seule commande de nettoyage nécessaire ici, et elle est asynchrone.
scw registry namespace delete "${NS_ID}" region=fr-par -o json | jq -r '.status'
until ! scw registry namespace get "${NS_ID}" region=fr-par > /dev/null 2>&1; do printf '.'; sleep 10doneecho " namespace disparu"La première sortie doit afficher deleting, la seconde finir par namespace disparu. N'arrêtez pas à la première : tant que le namespace reste listé, le stockage reste facturé. « J'ai demandé la suppression » n'est pas « c'est supprimé ».
Vérifiez enfin qu'il ne reste rien :
scw registry namespace list region=fr-par -o json | jq -r 'length'La sortie doit afficher 0.
Limites, quotas et plafonds
Section intitulée « Limites, quotas et plafonds »Les plafonds de nombre sont hors d'atteinte ; ce sont les prix et l'unicité qui contraignent.
| Plafond | Valeur | Source |
|---|---|---|
| Namespaces par Organisation | 99 999 | page des quotas |
| Images par Organisation | 99 999 | page des quotas |
| Versions d'une même image | illimité | FAQ Container Registry |
| Stockage d'images privées | 0,027 €/Go/mois | FAQ Container Registry |
| Images publiques gratuites | jusqu'à 75 Go | FAQ Container Registry |
| Sortie inter-régionale | 0,033 €/Go | FAQ Container Registry |
| Unicité du nom de namespace | globale, pas par compte | refus de l'API, 2026-09-12 |
Dépannage
Section intitulée « Dépannage »Les deux premiers symptômes portent le message exact renvoyé par l'API ou par le client.
| Symptôme | Cause | Solution |
|---|---|---|
{"message":"Namespace already exist"} | le nom est pris, au-delà de votre organisation | préfixer avec le nom du projet ou de l'équipe |
pull access denied … may require 'docker login' | image private et client non authentifié | scw registry login, ou passer l'image en public si c'est voulu |
docker pull répond Image is up to date sans rien télécharger | l'image est en cache local, aucun droit n'est exercé | docker rmi avant le test, sinon la mesure ne prouve rien |
insufficient_scope: authorization failed sur une image d'un autre projet | les identifiants du nœud ont pour portée le projet du cluster | créer un imagePullSecret et le référencer dans le pod |
Antipatterns à éviter
Section intitulée « Antipatterns à éviter »Ces quatre erreurs ont une racine commune : elles confondent le réglage affiché avec le droit réellement accordé.
| Antipattern | Conséquence | Discipline |
|---|---|---|
| Auditer la visibilité du namespace | une image publique passe inaperçue dans un namespace privé | auditer visibility image par image |
Conclure d'un docker pull réussi qu'on a le droit | l'image venait du cache local, rien n'a été exercé | supprimer l'image locale avant tout test d'accès |
Estimer sa facture avec le champ size de l'API | trois ordres de grandeur d'écart, c'est le manifeste | lire la console de facturation |
| Placer le registre dans une autre région que le cluster | chaque tirage devient du trafic facturé | même région pour le registre et le cluster |
Le registre sous l'angle Well-Architected
Section intitulée « Le registre sous l'angle Well-Architected »Sécurité
Section intitulée « Sécurité »Qu'est-ce qu'un anonyme peut tirer de votre registre aujourd'hui ? La question ne se répond pas en regardant le namespace, puisque chaque image peut contredire son réglage.
Discipline : lister périodiquement les images public, prouver chaque droit d'accès par un tirage sans authentification et sans cache local, et ne jamais écrire une clé d'API dans un fichier versionné, y compris dans un manifeste de secret.
Optimisation des coûts
Section intitulée « Optimisation des coûts »Qui paie le trafic de vos tirages ? Personne, tant que le registre et le cluster partagent la même région ; 0,033 €/Go dès qu'ils divergent.
Discipline : créer le namespace dans la région du cluster, garder des couches stables pour que la déduplication joue, et supprimer les namespaces de test, dont le stockage se facture indéfiniment sans jamais attirer l'attention.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- Créer un namespace prend moins d'une seconde et il est
readyimmédiatement. - Le nom d'un namespace est unique au-delà de votre organisation : l'API répond
Namespace already exist. - Une image poussée est en
inherit, ni publique ni privée : elle suit le namespace. - La visibilité par image surclasse celle du namespace : une seule image
publicest tirable par n'importe qui. - Un
docker pullsur une image en cache ne prouve aucun droit :docker rmid'abord, sinon la mesure est vide. - Le champ
sizede l'API est celui du manifeste : 1 235 octets annoncés pour 3 790 331 octets réels. - Un pod Kapsule tire une image privée du même projet sans
imagePullSecret: l'authentification se fait au niveau du nœud, hors des objets Kubernetes. - Le secret redevient nécessaire dès l'autre projet : mesuré, le tirage échoue en
insufficient_scope: authorization failed. - Republier un contenu identique prend 1 seconde et ne remonte aucune couche.
- Registre et cluster dans la même région : sinon chaque tirage coûte 0,033 €/Go.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Pools et autoscaling : Fait tirer vos images par des nœuds qui apparaissent et disparaissent tout seuls.
- Ingress ou Service LoadBalancer : Expose l'application construite à partir de ces images, en comptant ce qui se facture.
- Monter un cluster de version : Vérifie que les images se retirent correctement quand les nœuds sont remplacés.
Ressources externes
Section intitulée « Ressources externes »- FAQ Container Registry : la grille tarifaire complète, le détail des trafics entrants et sortants, et la règle d'unicité des noms de namespace.
- Déployer une image depuis Container Registry : la procédure officielle avec Image Pull Secret, à confronter à la mesure de cette leçon.
- Concepts de Container Registry : le vocabulaire officiel, namespace, image, tag et visibilité.
- Quotas de l'Organisation : les plafonds de namespaces et d'images selon le niveau de validation du compte.