pixel
Seite wählen

Docker-Registry und das Geheimnis des Löschens

von | Feb 24, 2016 | Betriebssysteme, Container, DevOps, Linux, NETWAYS, Team, Technology, Virtualisierung, Web Services

DockerLogo
Wenn man sich dazu entschließt, eine Docker-Registry zu installieren und zu konfigurieren, möchte man Images zentral abspeichern und verwalten können. Dies bietet viele Vorteile für den abteilungsübergreifenden Einsatz von Docker, aber auch ein paar Komplikationen im Umgang mit der Registry.
Wenn man mit dieser Registry arbeitet, entsteht irgendwann folgendes Problem. Das Löschen von Images funktioniert nicht wirklich.
Der Server ist fertig konfiguriert und man übermittelt Images an die Registry.
Der Speicherplatz wird zunehmend belegt, es liegen veraltete Images im Storage, die nicht mehr benötigt werden. Laut der Dokumentation von Docker, soll dieses Problem dadurch gelöst werden, dass man über die API Images “ganz einfach” löschen kann:
curl -k -X DELETE https://localhost:5000/v2/$imagename$/manifests/latest
Jedoch werden sich viele dann über diese (oder ähnliche) Fehlermeldung(en) ärgern:
{"errors":[{"code":"INVALID_DIGEST","message":"The digest is invalid"}]}
Laut Dokumentation, kann ein Image über die API nur dann gelöscht werden, wenn es durch den Namen und die Referenz(Tag, zum Beispiel “latest”) identifiziert werden kann, jedoch nur mittels “Digest”.
Ein Digest ist ein Wert um ein Image eindeutig identifizieren zu können. Er wird beim zum Beispiel bei einem Pull oder Push angezeigt. (Achtung! Der Digest ist nicht die Image ID, die beispielsweise bei einem “docker images” Command angezeigt wird.)

docker pull ubuntu
(...)
93f3596230c2: Pull complete
c06698a70f80: Pull complete
b6ea91fdc1f6: Pull complete
a53404c22cd2: Pull complete
Digest: sha256:c9f94277901034f3f40e73c861aee970da33dce9af2c02f13e1a4a72cdc0f8cb

Das Problem ist nun, dass der oben genannte DELETE nicht funktioniert. Eine kritische Alternative hierfür ist, auf der Commandline das Verzeichnis zu löschen
rm -rf ubuntu
Das Problem hierbei wären die Blobs, die als “Leiche” zurück bleiben würden. Wieso dies kritisch ist, möchte ich kurz versuchen zu erklären:
Jedes Image, besteht aus mehreren Layern, wobei die Layer aufeinander aufbauen. Der oberste Layer bekommt einen Tag (zum Beispiel “latest”). Blobs sind “BlobSums” (Digest) für die einzelnen Layer. Die einzelnen Layer sind wie der Digest des kompletten Images bei einem Pull, Push oder einem Api Request ersichtlich.
"schemaVersion": 1,
"name": "ubuntu",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
},
{
"blobSum": "sha256:a53404c22cd2ac9f68c352d17667ec1a2e36f22ca729983c40e1f24c106def6f"
},
{
"blobSum": "sha256:b6ea91fdc1f68eb0274174fd8c4eeea4baeee4986c942cbc7a21be82778e78b3"
},
{
(etc)

Beim Push in die Registry wird im Verzeichnis “blob” ein Eintrag für jeden Layer angelegt, mit der jeweiligen BlobSum. Löscht man nun ein “Image” aus der Registry, werden nur die Daten des Images gelöscht die im Verzeichnis “v2/repositories/$IMAGENAME” liegen. Auf den ersten Blick ist das Image gelöscht, denn in der Registry wird es nicht mehr als verfügbares Images zum Pull angezeigt. Die restlichen Layer jedoch und somit auch die Blobs, bleiben bestehen, womit sehr viel Speicherplatz mit nicht nutzbaren Daten belegt wird. Auch andere, von Docker erstellte Abhängigkeiten werden so nicht gelöscht. Das Problem ist dann, dass das Pushen des selben Images zurück in die Registry fehlerhaft sein wird, da versucht wird, Layer zu pushen, die schon hinterlegt sind und zu einem Image gehören aber nicht mehr zuordbar sind.
Komplizierter würde es werden, wenn man zum Beispiel nicht nur ein Image löschen möchte, sondern beispielsweise alle “untagged Images”. Dies sind veraltete Images, ohne einen Tag. Dies geschieht beispielsweise bei einem Push eines Images mit dem gleichem Namen.
Will oder kann man die Images nicht über die API löschen bietet “Burnettk” auf GitHub mit einem kleinen Skript eine gute Alternative.
Es handelt sich hier um ein Script, das ein Image anhand des Names identifiziert, und alles dazugehörige löscht. Was hierfür nötig ist, ist eine Environment Variable, die auf das Reporitory gesetzt wird. Als Beispiel:
export REGISTRY_DATA_DIR=/opt/registry_data/docker/registry/v2
Dannach kann das Script als normales Command genutzt werden. Um alle untagged Images zu löschen, kann man mit einer kleinen Schleife arbeiten, die innerhalb des Repoitory Verzeichnisses läuft:
for i in *; do delete_docker_registry_image --untagged --image $i; done;
Wenn man in diesem Verzeichnis, Images in einem weiteren Unterverzeichnis abspeichert, muss das Script kopiert und angepasst werden:
repositories_dir="repositories/$UNTERVERZEICHNIS"
An dieser Stelle bietet es sich auch an, diesen Löschvorgang in Form eines Crons zu automatisieren. Das Problem, dass die Registry zu wenig Speicherplatz frei hat, wäre so gelöst. Vielleicht kommt von Docker in den nächsten Docker-Engine Versionen eine brauchbare Lösung mit, jedoch ist das für mich die bisher beste Lösung.
dockerDocker, Docker, Docker!

Mattermost: Dein Messenger Dienst

Kommunikation in einem Unternehmen ist das A und O! Ganz egal, ob im Office oder im Homeoffice: mit einem Messenger Dienst kann man die Kommunikation im Homeoffice sehr gut überbrücken. Wenn Dein Unternehmen noch nicht den richtigen Messenger gefunden hat, ist dieser...

Ein Ausblick – Traefik Provider OpenStack

Bei unseren Online-Trainings von NETWAYS, werden jedem einzelnen Teilnehmer eine oder mehrere explizite VMs zur Verfügung gestellt, welche in der OpenStack-Umgebung von NWS gehostet werden. Hierbei benötigen die VMs jeweils öffentliche IPs, welche leider nicht...

HWgroup Ares 10 wird nicht mehr hergestellt

Im NETWAYS Shop gibt es seit vielen Jahren zahlreiche Produkte von HWgroup. Im Bereich Monitoring Hardware gehören diese zu den Bestsellern bei uns. Daher wollen wir unsere Kundschaft natürlich an Neuerungen teilhaben lassen. Aktuelle Krise zeigt auch im...