
Hallo, Habr! Ich prĂ€sentiere Ihnen eine Ăbersetzung des Artikels. Autor .
Heute sprechen wir darĂŒber, wie Docker den Speicherplatz des Hostsystems nutzt und wie wir diesen Platz von Ăberresten ungenutzter Images und Container befreien können.

Gesamtverbrauch
Docker ist eine groĂartige Sache, das bezweifelt wahrscheinlich heute kaum jemand. Vor ein paar Jahren hat dieses Produkt uns einen völlig neuen Weg eröffnet, jede Umgebung zu erstellen, zu liefern und zu starten, wodurch Ressourcen des Prozessors und des Arbeitsspeichers erheblich eingespart werden konnten. ZusĂ€tzlich dazu (und das ist fĂŒr einige vielleicht sogar das Wichtigste) hat Docker es uns ermöglicht, das Management des Lebenszyklus genutzter Arbeitsumgebungen unglaublich zu vereinfachen und zu standardisieren.
Allerdings hat man fĂŒr all die Vorteile des modernen Lebens auch einen Preis zu zahlen. Wenn wir Container starten, eigene Images herunterladen oder erstellen und komplexe Ăkosysteme aufbauen, mĂŒssen wir dafĂŒr bezahlen. Und zwar bezahlen wir unter anderem mit Speicherplatz.
Wenn Sie sich jemals gefragt haben, wie viel Speicher wirklich von Ihrem Docker auf Ihrem Rechner belegt wird, könnten Sie von der Ausgabe dieses Befehls unangenehm ĂŒberrascht sein:
$ docker system df 
Hier wird die Nutzung des Speichers durch Docker in verschiedenen Kategorien angezeigt:
- Images â Gesamter Speicherplatz der Images, die aus Registries heruntergeladen und in Ihrem System erstellt wurden;
- Container â Gesamter Speicherplatz, der von laufenden Containern verwendet wird (gemeint ist das gesamte Volumen der Schreib-Lese-Schichten aller Container);
- Lokale Volumes â Umfang der lokalen Speicher, die an Container angehĂ€ngt sind;
- Baucache â temporĂ€re Dateien, die wĂ€hrend des Erstellens von Images generiert wurden (beim Einsatz des BuildKit-Tools, das seit Docker Version 18.09 verfĂŒgbar ist).
Ich wette, dass Sie schon nach dieser einfachen AufzĂ€hlung den Drang verspĂŒren, die Festplatte von MĂŒll zu befreien und wertvolle Gigabyte zurĂŒckzugewinnen (Anmerkung des Ăbersetzers: besonders, wenn Sie fĂŒr diese Gigabyte monatlich Miete zahlen).
Speicherplatznutzung durch Container
Jedes Mal, wenn ein Container auf dem Hostsystem erstellt wird, werden im Verzeichnis /var/lib/docker mehrere Dateien und Verzeichnisse angelegt, von denen nachfolgend einige hervorgehoben werden:
- Das Verzeichnis /var/lib/docker/containers/ID_des_Containers â wenn der standardmĂ€Ăige Logging-Treiber verwendet wird, werden die Ereignisprotokolle im JSON-Format genau hier gespeichert. Zu detaillierte Protokolle sowie Protokolle, die niemand liest oder auf andere Weise verarbeitet, sind hĂ€ufig die Ursache fĂŒr das Ăberlaufen von Festplatten.
- Das Verzeichnis /var/lib/docker/overlay2 â enthĂ€lt die schreibbaren Schichten der Container (overlay2 â der bevorzugte Treiber in den meisten Linux-Distributionen). Wenn ein Container Daten in seinem Dateisystem speichert, werden diese genau in diesem Verzeichnis abgelegt.
Stellen wir uns ein System vor, auf dem ein jungfrĂ€ulicher Docker installiert ist, der noch nie Container oder Images gestartet hat. Sein Bericht ĂŒber den Festplattenspeicher wird folgendermaĂen aussehen:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 0 0 0B 0B
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BStarten wir einen Container, beispielsweise NGINX:
$ docker container run --name www -d -p 8000:80 nginx:1.16Was passiert mit der Festplatte:
- Images (Abbilder) belegen 126 MB, das ist das NGINX, das wir im Container gestartet haben;
- Container belegen lÀcherliche 2 Bytes.
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 1 1 126M 0B (0%)
Containers 1 1 2B 0B (0%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BLaut der Ausgabe haben wir noch keinen Speicherplatz, den wir freigeben könnten. Da 2 Bytes völlig unbedeutend sind, lassen Sie uns vorstellen, dass unser NGINX ĂŒberraschend 100 Megabyte Daten irgendwo geschrieben hat und darin eine Datei test.img genau dieser GröĂe erstellt hat.
$ docker exec -ti www
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]Untersuchen wir erneut die Festplattennutzung auf dem Host. Wir werden sehen, dass der Container dort 100 Megabyte belegt.
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 1 1 126M 0B (0%)
Containers 1 1 104.9MB 0B (0%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BIch denke, Ihr neugieriges Gehirn fragt sich bereits, wo unsere Datei test.img ist. Lassen Sie uns danach suchen:
$ find /var/lib/docker -type f -name test.img
/var/lib/docker/overlay2/83f177...630078/merged/test.img
/var/lib/docker/overlay2/83f177...630078/diff/test.imgOhne ins Detail zu gehen, kann festgestellt werden, dass die Datei test.img gĂŒnstig auf der Lese-Schreib-Ebene platziert ist, die vom Treiber overlay2 verwaltet wird. Wenn wir unseren Container jedoch anhalten, wird der Host uns darauf hinweisen, dass dieser Speicherplatz grundsĂ€tzlich freigegeben werden kann:
# Stopping the www container
$ docker stop www
# Visualizing the impact on the disk usage
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 1 1 126M 0B (0%)
Containers 1 0 104.9MB 104.9MB (100%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BWie können wir das tun? Durch das Löschen des Containers, was die Bereinigung des entsprechenden Speicherplatzes auf der Lese-Schreib-Ebene nach sich zieht.
Mit dem folgenden Befehl können Sie alle installierten Container auf einmal löschen und Ihre Festplatte von allen durch diese erzeugten Lese-Schreib-Dateien bereinigen:
$ docker container prune
WARNING! Dies entfernt alle gestoppten Container.
Sind Sie sicher, dass Sie fortfahren möchten? [y/N] y
Gelöschte Container:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2
Insgesamt zurĂŒckgewonnener Speicherplatz: 104,9 MBDamit haben wir 104,9 Megabyte durch das Löschen des Containers freigegeben. Da wir jedoch das zuvor heruntergeladene Image nicht mehr verwenden, wird auch dieses zum Kandidaten fĂŒr die Löschung und fĂŒr die Freisetzung unserer Ressourcen:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 1 0 126M 126M (100%)
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BAchtung: Solange das Image von mindestens einem Container verwendet wird, können Sie diesen Trick nicht anwenden.
Der Befehl prune, den wir oben verwendet haben, hat nur Wirkung auf gestoppte Container. Wenn wir sowohl gestoppte als auch laufende Container löschen möchten, sollten wir einen dieser Befehle verwenden:
# Historical command
$ docker rm -f $(docker ps âaq)
# More recent command
$ docker container rm -f $(docker container ls -aq)Hinweis am Rande: Wenn Sie beim Starten des Containers die Option ârm verwenden, wird bei dessen Stopp der gesamte Speicherplatz freigegeben, den er belegt hat.
Speichernutzung durch Images
Vor einigen Jahren war die GröĂe eines Images von mehreren Hundert Megabyte völlig normal: Das Ubuntu-Image wog 600 Megabyte, und das Microsoft .Net-Image mehrere Gigabyte. In diesen alten Zeiten konnte der Download selbst eines einzigen Images groĂen Schaden an Ihrem verfĂŒgbaren Speicherplatz anrichten, selbst wenn Sie die Ebenen zwischen Images geteilt haben. Heute â Dank der Götter â wiegen die Images viel weniger, aber selbst in diesem Fall kann man schnell die vorhandenen Ressourcen ĂŒberlasten, wenn man keine VorsichtsmaĂnahmen trifft.
Es gibt mehrere Arten von Images, die fĂŒr den Endbenutzer nicht direkt sichtbar sind:
- IntermediĂ€re Images, auf deren Grundlage andere Images erstellt wurden â sie können nicht gelöscht werden, wenn Sie Container auf der Basis dieser "anderen" Images verwenden;
- HĂ€ngende Images â das sind solche intermediĂ€ren Images, auf die keiner der laufenden Container verweist â sie können gelöscht werden.
- Mit dem folgenden Befehl können Sie in Ihrem System nach hÀngenden Images suchen:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
none none 21e658fe5351 vor 12 Minuten 71.3MBSie können sie folgendermaĂen löschen:
$ docker image rm $(docker image ls -f dangling=true -q)Wir können auch den Unterbefehl prune verwenden:
$ docker image prune
WARNUNG! Dies wird alle hÀngenden Images entfernen.
Sind Sie sicher, dass Sie fortfahren möchten? [y/N] y
Gelöschte Images:
gelöscht: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
gelöscht: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
gelöscht: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
gelöscht: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
gelöscht: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f
Insgesamt wiedergewonnener Speicherplatz: 12,9 kBFalls wir ausnahmsweise alle Images (nicht nur hÀngende) mit einem Befehl löschen möchten, können wir es so machen:
$ docker image rm $(docker image ls -q)Verwendung von Speicherplatz durch Volumes
Volumes werden verwendet, um Daten auĂerhalb des Dateisystems des Containers zu speichern. Zum Beispiel, wenn wir die Ergebnisse der Arbeit einer Anwendung speichern möchten, um sie anderweitig zu verwenden. Ein hĂ€ufiges Beispiel sind Datenbanken.
Lassen Sie uns einen MongoDB-Container starten, ein externes Volume montieren und ein Backup der Datenbank aus der Datei bck.json wiederherstellen:
# Running a mongo container
$ docker run --name db -v $PWD:/tmp -p 27017:27017 -d mongo:4.0
# Importing an existing backup (from a huge bck.json file)
$ docker exec -ti db mongoimport
--db 'test'
--collection 'demo'
--file /tmp/bck.json
--jsonArrayDie Daten werden auf der Host-Maschine im Verzeichnis /var/lib/docker/volumes gespeichert. Aber warum nicht im Container im Lese-Schreib-Zugriff? Weil im Dockerfile des MongoDB-Images das Verzeichnis /data/db (in dem MongoDB standardmĂ€Ăig seine Daten speichert) als Volume definiert ist.

Hinweise: Viele Images, aus deren Verarbeitung Daten entstehen sollten, verwenden Volumes zur Speicherung dieser Daten.
Wenn wir mit MongoDB fertig sind und den Container stoppen (oder vielleicht sogar löschen), wird das Volume nicht gelöscht. Es wird weiterhin unser wertvolles Speicherplatz belegen, bis wir es ausdrĂŒcklich mit folgendem Befehl löschen:
$ docker volume rm $(docker volume ls -q)Oder wir können den uns bereits bekannten Unterbefehl prune verwenden:
$ docker volume prune
WARNUNG! Dies entfernt alle lokalen Volumes, die nicht von mindestens einem Container verwendet werden.
Sind Sie sicher, dass Sie fortfahren möchten? [y/N] y
Gelöschte Volumes:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da
Gesamter zurĂŒckgewonnener Speicherplatz: 25,82 GB
luc@saturn:~$Verwendung des Speichers fĂŒr den Cache beim Erstellen von Images
In Docker 18.09 hat der Prozess zur Erstellung von Images einige Ănderungen erfahren, dank des Tools BuildKit. Dieses Tool erhöht die Geschwindigkeit des Prozesses und optimiert die Verwaltung von Datenspeicherung und Sicherheit. Hier werden wir nicht alle Details dieses bemerkenswerten Werkzeugs betrachten, sondern uns lediglich ansehen, wie es die Nutzung des Speicherplatzes beeinflusst.
Angenommen, wir haben eine ganz einfache Node.Js-Anwendung:
- Die Datei index.js startet einen einfachen HTTP-Server, der auf jede eingehende Anfrage mit einer Zeile antwortet:
- Die Datei package.json definiert die AbhĂ€ngigkeiten, von denen nur expressjs zur AusfĂŒhrung des HTTP-Servers verwendet wird:
$ cat index.js
var express = require('express');
var util = require('util');
var app = express();
app.get('/', function(req, res) {
res.setHeader('Content-Type', 'text/plain');
res.end(util.format("%s - %s", new Date(), 'Got Request'));
});
app.listen(process.env.PORT || 80);$ cat package.json
{
"name": "testnode",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"express": "^4.14.0"
}
}Das Dockerfile zum Erstellen des Images sieht folgendermaĂen aus:
FROM node:13-alpine
COPY package.json /app/package.json
RUN cd /app && npm install
COPY . /app/
WORKDIR /app
EXPOSE 80
CMD ["npm", "start"]Lassen Sie uns das Image auf herkömmliche Weise ohne Verwendung von BuildKit erstellen:
$ docker build -t app:1.0 .Wenn wir die Nutzung des Speicherplatzes ĂŒberprĂŒfen, sehen wir, dass nur das Basisimage (node:13-alpine) und das endgĂŒltige Image (app:1.0) Platz beanspruchen:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 2 0 109.3MB 109.3MB (100%)
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BLassen Sie uns die zweite Version unserer Anwendung erstellen, nun mit Verwendung von BuildKit. Dazu mĂŒssen wir lediglich die Umgebungsvariable DOCKER_BUILDKIT auf 1 setzen:
$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .Wenn wir jetzt die Nutzung des Speichers ĂŒberprĂŒfen, sehen wir, dass jetzt der Build-Cache (build-cache) beteiligt ist:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMBAR
Images 2 0 109,3MB 109,3MB (100%)
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 11 0 8.949kB 8.949kBUm ihn zu bereinigen, verwenden wir den folgenden Befehl:
$ docker builder prune
WARNUNG! Dies entfernt allen nicht mehr verwendeten Build-Cache.
Sind Sie sicher, dass Sie fortfahren möchten? [y/N] y
Gelöschte Build-Cache-Objekte:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi
Gesamt wiederhergestellter Speicherplatz: 8.949kBAlles bereinigen!
Wir haben also die Bereinigung des Festplattenspeichers betrachtet, der von Containern, Images und Volumes belegt wird. Dabei hilft uns der Unterbefehl prune. Dieser kann jedoch auch auf Systemebene von Docker verwendet werden und bereinigt alles, was er kann:
$ docker system prune
WARNUNG! Dies entfernt:
- alle gestoppten Container
- alle Netzwerke, die von mindestens einem Container nicht verwendet werden
- alle nicht mehr verwendeten Images
- allen nicht mehr verwendeten Build-Cache
Sind Sie sicher, dass Sie fortfahren möchten? [y/N]Wenn Sie aus irgendeinem Grund Speicherplatz auf Ihrem Docker-Rechner sparen, sollten Sie sich angewöhnen, diesen Befehl regelmĂ€Ăig auszufĂŒhren.
Quelle: habr.com
