web-dev-qa-db-fra.com

Comment supprimer des images d'un registre de docker privé?

J'exécute un registre de docker privé et je veux supprimer toutes les images sauf le latest d'un référentiel. Je ne veux pas supprimer le référentiel entier, mais seulement certaines des images qu'il contient. Les docs de l'API ne mentionnent pas un moyen de faire cela, mais c'est sûrement possible?

126
Leo

Actuellement, vous ne pouvez pas utiliser l'API de registre pour cette tâche. Il vous permet uniquement de supprimer un référentiel ou une balise spécifique.

En général, la suppression d'un référentiel signifie que toutes les balises associées à ce référentiel sont supprimées.

Supprimer une étiquette signifie que l’association entre une image et une étiquette est supprimée.

Aucune de ces réponses ne supprimera une seule image. Ils sont laissés sur votre disque.


Workaround

Pour cette solution de contournement, vous devez stocker les images de votre menu fixe dans votre magasin.

Une solution de contournement pour votre solution serait de supprimer toutes les balises sauf les plus récentes et ainsi potentiellement de supprimer la référence aux images associées. Ensuite, vous pouvez exécuter ce script pour supprimer toutes les images, qui ne sont référencées par aucune balise ou l'ascendance de toute image utilisée. .

Terminologie (images et tags)

Prenons un graphique d’image comme celui-ci où les lettres majuscules (A, B, ...) représentent des ID d’image courts et <- signifie qu’une image est basée sur une autre image:

 A <- B <- C <- D

Maintenant, nous ajoutons des tags à l'image:

 A <- B <- C <- D
           |    |
           |    <version2>
           <version1>

Ici, la balise <version1> fait référence à l'image C et la balise <version2> fait référence à l'image D.

Affiner votre question

Dans votre question, vous avez dit que vous vouliez supprimer

toutes les images sauf latest

. Maintenant, cette terminologie n'est pas tout à fait correcte. Vous avez mélangé des images et des tags. En regardant le graphique, je pense que vous conviendrez que la balise <version2> représente la dernière version. En fait, selon cette question vous pouvez avoir une balise qui représente la dernière version:

 A <- B <- C <- D
           |    |
           |    <version2>
           |    <latest>
           <version1>

Puisque la balise <latest> fait référence à l'image D, je vous le demande: voulez-vous vraiment supprimer tout sauf l'image D? Probablement pas!

Que se passe-t-il si vous supprimez un tag?

Si vous supprimez la balise <version1> à l'aide de l'API Docker REST, vous obtiendrez ceci:

 A <- B <- C <- D
                |
                <version2>
                <latest>

N'oubliez pas: Docker ne supprimera jamais une image! Même si c'était le cas, dans ce cas, il ne peut pas supprimer une image, car l'image C fait partie de l'ascendance de l'image D qui est balisée.

Même si vous utilisez ce script, aucune image ne sera supprimée.

Quand une image peut être supprimée

Sous la condition que vous puissiez contrôler le moment où une personne peut accéder à votre registre ou y accéder par la poste (par exemple, en désactivant l'interface REST). Vous pouvez supprimer une image d'un graphe d'image si aucune autre image n'est basée sur celle-ci et si aucune balise n'y fait référence.

Notez que dans le graphique ci-dessous, l'image D est non basée sur C mais sur B. Par conséquent, D ne dépend pas de C. Si vous supprimez la balise <version1> dans ce graphique, l’image C ne sera utilisée par aucune image et ce script peut l'enlever.

 A <- B <--------- D
      \            |
       \           <version2>
        \          <latest>
         \ <- C
              |
              <version1>

Après le nettoyage, votre graphique d’image se présente comme suit:

 A <- B <- D
           |
           <version2>
           <latest>

C'est ce que tu veux?

101
Konrad Kleine

J'ai rencontré le même problème avec mon registre, puis j'ai essayé la solution indiquée ci-dessous à partir d'une page de blog. Ça marche.

Étape 1: Liste des catalogues

Vous pouvez lister vos catalogues en appelant cette URL:

http://YourPrivateRegistyIP:5000/v2/_catalog

La réponse sera dans le format suivant:

{
  "repositories": [
    <name>,
    ...
  ]
}

Étape 2: Liste des balises pour le catalogue associé

Vous pouvez lister les tags de votre catalogue en appelant cette URL:

http://YourPrivateRegistyIP:5000/v2/<name>/tags/list

La réponse sera dans le format suivant:

{
"name": <name>,
"tags": [
    <tag>,
    ...
]

}

Étape 3: Répertoriez la valeur manifeste du tag associé

Vous pouvez exécuter cette commande dans le conteneur de registre de docker:

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X GET http://localhost:5000/v2/<name>/manifests/<tag> 2>&1 | grep Docker-Content-Digest | awk '{print ($3)}'

La réponse sera dans le format suivant:

sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

Exécutez la commande ci-dessous avec une valeur manifeste:

curl -v --silent -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -X DELETE http://127.0.0.1:5000/v2/<name>/manifests/sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073

Étape 4: Supprimer les manifestes marqués

Exécutez cette commande dans votre conteneur de registre de docker:

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

Voici mon config.yml

root@c695814325f4:/etc# cat /etc/docker/registry/config.yml
version: 0.1
log:
  fields:
  service: registry
storage:
    cache:
        blobdescriptor: inmemory
    filesystem:
        rootdirectory: /var/lib/registry
    delete:
        enabled: true
http:
    addr: :5000
    headers:
        X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
52
Yavuz Sert

Le registre actuel v2 prend en charge la suppression via DELETE /v2/<name>/manifests/<reference>

Voir: https://github.com/docker/distribution/blob/master/docs/spec/api.md#deleting-an-image

Utilisation de travail: https://github.com/byrnedo/docker-reg-tool

Edit: Le manifeste <reference> ci-dessus peut être récupéré de la demande à

GET /v2/<name>/manifests/<tag>

et en vérifiant l'en-tête Docker-Content-Digest dans la réponse.

49
byrnedo

Problème 1

Vous avez mentionné qu'il s'agissait de votre registre de docker privé. Vous devez donc probablement vérifier API de registre au lieu de doc de l'API de registre Hub , qui est le lien que vous avez fourni.

Problème 2

l'API de registre de docker est un protocole client/serveur, il appartient à l'implémentation du serveur de supprimer ou non les images dans le back-end. (Je suppose)

DELETE /v1/repositories/(namespace)/(repository)/tags/(tag*)

Explication détaillée

Ci-dessous, je vous explique comment cela fonctionne maintenant, à partir de votre description et de ma compréhension de vos questions.

Vous utilisez un registre de docker privé, j'utilise celui par défaut et j'écoute dans le port 5000

docker run -d -p 5000:5000 registry

Ensuite, je marque l’image locale et pousse dessus.

$ docker tag ubuntu localhost:5000/ubuntu
$ docker Push localhost:5000/ubuntu
The Push refers to a repository [localhost:5000/ubuntu] (len: 1)
Sending image list
Pushing repository localhost:5000/ubuntu (1 tags)
511136ea3c5a: Image successfully pushed
d7ac5e4f1812: Image successfully pushed
2f4b4d6a4a06: Image successfully pushed
83ff768040a0: Image successfully pushed
6c37f792ddac: Image successfully pushed
e54ca5efa2e9: Image successfully pushed
Pushing tag for rev [e54ca5efa2e9] on {http://localhost:5000/v1/repositories/ubuntu/tags/latest}

Après cela, vous pouvez utiliser API de registre pour vérifier son existence dans votre registre de docker privé.

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags
{"latest": "e54ca5efa2e962582a223ca9810f7f1b62ea9b5c3975d14a5da79d3bf6020f37"}

Maintenant, je peux supprimer le tag en utilisant cette API!

$ curl -X DELETE localhost:5000/v1/repositories/ubuntu/tags/latest
true

Vérifiez à nouveau, la balise n'existe pas dans votre serveur de registre privé

$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags/latest
{"error": "Tag not found"}
15
Larry Cai

C'est vraiment moche, mais ça marche, le texte est testé sur la base de registres: 2.5.1. Je n’ai pas réussi à faire en sorte que la suppression fonctionne correctement même après la mise à jour de la configuration pour permettre la suppression. L'identifiant était vraiment difficile à récupérer, il a fallu se connecter pour l'obtenir, peut-être un malentendu. Quoi qu'il en soit, les travaux suivants:

  1. Se connecter au conteneur

    docker exec -it registry sh
    
  2. Définissez les variables correspondant à votre conteneur et à votre version de conteneur:

    export NAME="google/cadvisor"
    export VERSION="v0.24.1"
    
  3. Déplacer vers le répertoire de registre:

    cd /var/lib/registry/docker/registry/v2
    
  4. Supprimer les fichiers liés à votre hachage:

    find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
    
  5. Supprimer les manifestes:

    rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
    
  6. Se déconnecter

    exit
    
  7. Lancer le GC:

    docker exec -it registry  bin/registry garbage-collect  /etc/docker/registry/config.yml
    
  8. Si tout a été fait correctement, des informations sur les blobs supprimés sont affichées.

9
hirro

Il y a des clients (en Python, Ruby, etc.) qui font exactement cela. À mon goût, il n'est pas viable d'installer un runtime (par exemple, Python) sur mon serveur de registre, juste pour gérer mon registre!


Donc deckschrubber est ma solution:

go get github.com/fraunhoferfokus/deckschrubber
$GOPATH/bin/deckschrubber

les images plus anciennes qu'un âge donné sont automatiquement supprimées. L'âge peut être spécifié en utilisant -year, -month, -day, ou une combinaison de ceux-ci:

$GOPATH/bin/deckschrubber -month 2 -day 13 -registry http://registry:5000

UPDATE: voici une courte introduction sur deckschrubber.

8
Yan Foto

Simple Ruby script basé sur this answer: registry_cleaner .

Vous pouvez l'exécuter sur une machine locale:

./registry_cleaner.rb --Host=https://registry.exmpl.com --repository=name --tags_count=4

Et puis sur la machine de registre, supprimez les blobs avec /bin/registry garbage-collect /etc/docker/registry/config.yml.

0
Ilya Krigouzov

Au-dessous de Script Bash Supprime toutes les balises situées dans la base de registre sauf la dernière.

for D in /registry-data/docker/registry/v2/repositories/*; do
if [ -d "${D}" ]; then
    if [ -z "$(ls -A ${D}/_manifests/tags/)" ]; then
        echo ''
    else
        for R in $(ls -t ${D}/_manifests/tags/ | tail -n +2); do
            digest=$(curl -k -I -s -H -X GET http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/${R} -H 'accept: application/vnd.docker.distribution.manifest.v2+json'  | grep Docker-Content-Digest | awk '{print $2}' )
            url="http://xx.xx.xx.xx:5000/v2/$(basename  ${D})/manifests/$digest"
            url=${url%$'\r'}
            curl -X DELETE -k -I -s   $url -H 'accept: application/vnd.docker.distribution.manifest.v2+json' 
        done
    fi
fi
done

Après cette course

docker exec $(docker ps | grep registry | awk '{print $1}') /bin/registry garbage-collect /etc/docker/registry/config.yml
0
Shree Tiwari

Cette image de menu fixe inclut un script bash pouvant être utilisé pour supprimer des images d'un registre v2 distant: https://hub.docker.com/r/vidarl/remove_image_from_registry/

0
Vidar Langseid