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?
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.
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. .
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
.
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!
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.
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?
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.
Vous pouvez lister vos catalogues en appelant cette URL:
http://YourPrivateRegistyIP:5000/v2/_catalog
La réponse sera dans le format suivant:
{
"repositories": [
<name>,
...
]
}
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>,
...
]
}
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
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
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.
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"}
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:
Se connecter au conteneur
docker exec -it registry sh
Définissez les variables correspondant à votre conteneur et à votre version de conteneur:
export NAME="google/cadvisor"
export VERSION="v0.24.1"
Déplacer vers le répertoire de registre:
cd /var/lib/registry/docker/registry/v2
Supprimer les fichiers liés à votre hachage:
find . | grep `ls ./repositories/$NAME/_manifests/tags/$VERSION/index/sha256`| xargs rm -rf $1
Supprimer les manifestes:
rm -rf ./repositories/$NAME/_manifests/tags/$VERSION
Se déconnecter
exit
Lancer le GC:
docker exec -it registry bin/registry garbage-collect /etc/docker/registry/config.yml
Si tout a été fait correctement, des informations sur les blobs supprimés sont affichées.
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.
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
.
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
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/