Comment supprimer des images d'un registre docker privé?
je dirige un registre docker privé, et je veux supprimer toutes les images sauf le latest
d'un dépôt. Je ne veux pas supprimer tout le dépôt, juste quelques-unes des images qu'il contient. Le API docs ne mentionne pas une façon de le faire, mais est-ce possible?
8 réponses
Actuellement, vous ne pouvez pas utiliser l'API Registre pour cette tâche. Il ne vous permet de supprimer qu'un dépôt ou une balise spécifique.
en général, supprimer un dépôt signifie que toutes les étiquettes associées à ce rapport sont supprimées.
supprimer une balise signifie que l'association entre une image et une balise est supprimée.
aucun des éléments ci-dessus ne supprimera une seule image. Ils sont laissés sur votre disque.
solution de Contournement
pour cette solution, vous devez avoir vos images docker stockées localement.
une solution de rechange pour votre solution serait de supprimer toutes les balises sauf les plus récentes et donc potentiellement supprimer la référence aux images associées. Ensuite, vous pouvez lancer ce script pour supprimer toutes les images, qui ne sont référencées par aucune étiquette ou l'ascendance de toute image utilisée.
terminologie (images et étiquettes)
considérez un graphique d'image comme ceci où les lettres majuscules ( A
, B
, ...) représentent des IDs 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, l'étiquette <version1>
renvoie à l'image C
et l'étiquette <version2>
renvoie à l'image D
.
affiner votre question
Dans votre question, vous avez dit que vous vouliez supprimer
toutes les images sauf le
latest
. 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 seriez d'accord que l'étiquette <version2>
représente la dernière version. En fait, selon cette question vous pouvez avoir une étiquette qui représente la dernière version:
A <- B <- C <- D
| |
| <version2>
| <latest>
<version1>
depuis le <latest>
image de référence de l'étiquette D
je vous demande: Voulez - vous vraiment supprimer tout sauf l'image D
? Probablement pas!
que se passe-t-il si vous supprimez une étiquette?
si vous supprimez la balise <version1>
en utilisant L'API Docker REST vous obtiendrez ceci:
A <- B <- C <- D
|
<version2>
<latest>
souvenez-vous: Docker ne supprimera jamais une image! Même s'il l'a fait, dans ce cas il ne peut pas supprimer une image, puisque l'image C
fait partie de l'ascendance pour l'image D
qui est marquée.
même si vous utilisez ce script , aucune image ne sera supprimée.
Lorsqu'une image peut être supprimée
sous le condition que vous pouvez contrôler quand quelqu'un peut tirer ou pousser à votre registre (par exemple en désactivant L'interface REST). Vous pouvez supprimer une image d'un graphique d'image si aucune autre image n'est basée sur elle et qu'aucune balise ne s'y réfère.
notez que dans le graphique suivant, l'image D
est pas basé sur C
mais sur B
. Par conséquent, D
ne dépend pas de C
. Si vous supprimez l'étiquette <version1>
dans ce graphe, l'image C
ne sera utilisée par aucune image et ce script peut le supprimer.
A <- B <--------- D
\ |
\ <version2>
\ <latest>
\ <- C
|
<version1>
après le nettoyage votre graphique d'image ressemble à ceci:
A <- B <- D
|
<version2>
<latest>
C'est ça que tu veux?
j'ai fait face au même problème avec mon registre puis j'ai essayé la solution indiquée ci-dessous à partir d'une page de blog. Elle fonctionne.
Étape 1: Liste des catalogues de
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 les catalogue
vous pouvez lister les étiquettes 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: Liste de la valeur du Manifeste pour l'étiquette connexe
vous pouvez exécuter cette commande dans le conteneur docker registry:
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 ()}'
la réponse sera dans le format suivant:
sha256:6de813fb93debd551ea6781e90b02f1f93efab9d882a6cd06bbd96a07188b073
exécuter la commande ci-dessous avec la 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 Docker registy:
bin/registry garbage-collect /etc/docker/registry/config.yml
voici ma 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
le registre actuel v2
supporte maintenant la suppression via DELETE /v2/<name>/manifests/<reference>
voir: https://github.com/docker/distribution/blob/master/docs/spec/api.md#deleting-an-image
usage courant: https://github.com/byrnedo/docker-reg-tool
Edit:
Le manifeste <reference>
ci-dessus peut être récupéré à partir de la demande à
GET /v2/<name>/manifests/<tag>
et vérification de l'en-tête Docker-Content-Digest
dans la réponse.
Problème 1
vous avez mentionné qu'il s'agissait de votre registre docker privé, de sorte que vous devez probablement cocher API de Registre au lieu de Hub registry API doc , qui est le lien que vous avez fourni.
problème 2
L'API de registre docker est un protocole client / serveur, c'est à l'implémentation du serveur de décider 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 Démo comment cela fonctionne maintenant à partir de votre description que ma compréhension pour vos questions.
vous exécutez vous exécutez Docker privé registre, j'utilise celui par défaut et écouter dans 5000
port
docker run -d -p 5000:5000 registry
puis je marque l'image locale et je pousse dedans.
$ 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 qu'il existe dans votre registre docker privé
$ curl -X GET localhost:5000/v1/repositories/ubuntu/tags
{"latest": "e54ca5efa2e962582a223ca9810f7f1b62ea9b5c3975d14a5da79d3bf6020f37"}
maintenant je peux supprimer la balise en utilisant cette API !!
$ curl -X DELETE localhost:5000/v1/repositories/ubuntu/tags/latest
true
Vérifiez encore, 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"}
C'est vraiment laid mais ça marche, le texte est testé sur le registre:2.5.1. Je n'ai pas réussi à faire en sorte que delete fonctionne correctement même après avoir mis à jour la configuration pour activer delete. L'ID é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:
-
Se connecter au conteneur
docker exec -it registry sh
-
définir les variables correspondant à votre conteneur et version conteneur:
export NAME="google/cadvisor" export VERSION="v0.24.1"
-
passer à l'annuaire du registre:
cd /var/lib/registry/docker/registry/v2
-
supprimer les fichiers relatifs à votre hachage:
find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf
-
supprimer les manifestes:
rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
-
Déconnexion
exit
-
Exécuter la GC:
docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml
-
si tout a été fait correctement, certaines informations sur les blobs supprimés sont affichés.
il y a des clients (en Python, Ruby, etc) qui font exactement cela. A mon goût, il n'est pas soutenable d'installer un runtime (par exemple Python) sur mon serveur de registre, juste pour gérer mon registre!
Donc deckschrubber
c'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 combinaison des deux:
$GOPATH/bin/deckschrubber -month 2 -day 13 -registry http://registry:5000
mise à JOUR : voici une courte introduction sur deckschrubber.
cette image de docker inclut un script bash qui peut être utilisé pour supprimer des images d'un registre v2 distant : https://hub.docker.com/r/vidarl/remove_image_from_registry/
ci-dessous Bas Bash Script supprime toutes les étiquettes situées dans le 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 }' )
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 }') /bin/registry garbage-collect /etc/docker/registry/config.yml