Seite wählen

Docker-Registry und das Geheimnis des Löschens

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

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!

0 Kommentare

Trackbacks/Pingbacks

  1. And again: Das Löschen von Images in der Docker-Registry › NETWAYS Blog - […] das bereits sehr viel Zeit in Anspruch genommen hat. In einem früheren Blogpost wurde eine Variante vorgestellt, die mit einem…

Einen Kommentar abschicken

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Vielseitige Einblicke der Abteilungswoche bei NETWAYS

In der modernen Arbeitswelt ist es wichtig, über den eigenen Tellerrand hinauszuschauen und ein Verständnis für verschiedene Bereiche eines Unternehmens zu entwickeln. Genau aus diesem Grund wurde bei NETWAYS die Idee der Abteilungswoche geboren. In dieser Woche hatte...

Monthly Snap März 2024

Endlich Frühling in Nürnberg! Die Laune ist doch morgens gleich besser, wenn es schon hell ist, wenn man aus dem Haus geht. Wir haben im März viele schöne Blogposts für Euch gehabt. Falls Ihr welche davon verpasst hat, hier ein Überblick für Euch. Aber natürlich...