Docker Tipps: Reinigen Sie Ihre Maschine von unnötigem Ballast

Docker Tipps: Reinigen Sie Ihre Maschine von unnötigem Ballast

Hallo, Habr! Ich präsentiere Ihnen die Übersetzung des Artikels "Docker Tipps: Bereinigen Sie Ihre lokale Maschine" Autor Luc Juggery.

Heute sprechen wir darüber, wie Docker Speicherplatz auf der Hostmaschine verwendet und wie wir diesen Speicherplatz von Resten ungenutzter Images und Container befreien können.


Docker Tipps: Reinigen Sie Ihre Maschine von unnötigem Ballast

Gesamtverbrauch

Docker ist eine großartige Sache, und wahrscheinlich gibt es heute nur wenige, die daran zweifeln. Vor nur wenigen Jahren hat dieses Produkt uns eine völlig neue Möglichkeit geboten, jede Art von Umgebung zu erstellen, bereitzustellen und auszuführen. Dadurch konnten wir die CPU- und Arbeitsspeicherauslastung erheblich reduzieren. Darüber hinaus (und für manche wird das sogar das Wichtigste sein) hat Docker es uns ermöglicht, das Management des Lebenszyklus der verwendeten Arbeitsumgebungen unglaublich zu vereinfachen und zu standardisieren.

Doch für all diese Vorzüge des modernen Lebens müssen wir bezahlen. Wenn wir Container starten, eigene Images herunterladen oder erstellen und komplexe Ökosysteme aufbauen, zahlen wir dafür. Und wir zahlen auch in Form von Speicherplatz.

Wenn Sie sich nie gefragt haben, wie viel Speicherplatz tatsächlich von Ihrem Docker belegt wird, könnten Sie von der Ausgabe dieses Befehls unangenehm überrascht sein:

$ docker system df

Docker Tipps: Reinigen Sie Ihre Maschine von unnötigem Ballast

Hier wird die Disknutzung durch Docker in verschiedenen Aspekten angezeigt:

  • Images – die Gesamtgröße der Bilder, die aus dem Image-Repository heruntergeladen und in Ihrem System erstellt wurden;
  • Container – der gesamte Speicherplatz, der von gestarteten Containern verwendet wird (gemeint ist das gesamte Schreib-Lese-Schichtvolumen aller Container);
  • Lokale Volumes – das Volumen der lokalen Speicher, die an Container gemountet sind;
  • Build-Cache – temporäre Dateien, die während des Erstellungsprozesses von Images generiert werden (bei Verwendung des BuildKit, das seit Docker Version 18.09 verfügbar ist).

Ich wette, dass Sie nach diesem einfachen Aufzählung brennen, den Speicher von Müll zu befreien und wertvolle Gigabytes zurückzubekommen (Anm. d. Übersetzers: besonders, wenn Sie für diese Gigabytes monatlich Miete zahlen).

Speichernutzung durch Container

Jedes Mal, wenn ein Container auf dem Host-System erstellt wird, werden im Verzeichnis /var/lib/docker mehrere Dateien und Verzeichnisse angelegt, darunter hervorzuheben sind die folgenden:

  • Das Verzeichnis /var/lib/docker/containers/ID_Container – wenn der Standard-Logging-Treiber verwendet wird, werden hier die Ereignisprotokolle im JSON-Format gespeichert. Zu detaillierte Protokolle sowie Protokolle, die niemand liest oder auf andere Weise verarbeitet, führen häufig zu einer Festplattenüberlastung.
  • 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 hier abgelegt.

Stellen wir uns ein System vor, auf dem ein jungfräulicher Docker installiert ist, der noch nie Container gestartet oder Images erstellt hat. Sein Bericht über die Datenträgerspeicherung würde 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         0B

Lassen Sie uns einen Container starten, zum Beispiel NGINX:

$ docker container run --name www -d -p 8000:80 nginx:1.16

Was mit dem Speicherplatz passiert:

  • Images belegen 126 MB, das ist das NGINX, das wir im Container gestartet haben;
  • Container belegen lächerliche 2 Byte.

$ 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         0B

Aus der Ausgabe geht hervor, dass wir noch keinen Speicherplatz haben, den wir freigeben könnten. Da 2 Byte absolut nicht ernst zu nehmen sind, stellen wir uns vor, dass unser NGINX plötzlich 100 Megabyte an Daten irgendwo geschrieben hat und eine Datei namens test.img in 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 Verwendung des Speicherplatzes 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         0B

Ich denke, Ihr neugieriger Verstand fragt sich bereits, wo sich unsere Datei test.img befindet. 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.img

Ohne ins Detail zu gehen, kann festgehalten werden, dass die Datei test.img ideal auf der Lese-Schreib-Ebene liegt, die vom overlay2-Treiber verwaltet wird. Wenn wir unseren Container stoppen, 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         0B

Wie können wir das erreichen? Durch das Löschen des Containers, was zur Bereinigung des entsprechenden Speicherplatzes auf der Lese-Schreib-Ebene führt.

Mit dem folgenden Befehl können Sie alle installierten Container auf einmal löschen und Ihren Speicher von allen daraus entstandenen Dateien auf der Lese-Schreib-Ebene befreien:

$ docker container prune
WARNUNG! Dadurch werden alle gestoppten Container entfernt.
Sind Sie sicher, dass Sie fortfahren möchten? [y/N] y
Gelöschte Container:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2

Total freigegebener Speicher: 104,9 MB

Damit 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 zu einem Kandidaten für die Löschung, um unsere Ressourcen weiter freizugeben:

$ 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         0B

Achtung: Solange das Image von mindestens einem Container verwendet wird, können Sie diesen Trick nicht anwenden.

Der oben eingesetzte Befehl "prune" hat nur Wirkung auf gestoppte Container. Wenn wir nicht nur gestoppte, sondern auch laufende Container entfernen wollen, 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: Wenn beim Starten eines Containers die Option —rm verwendet wird, wird der gesamte Speicherplatz, den er beansprucht hat, bei seiner Beendigung freigegeben.

Speichernutzung durch Images

Vor einigen Jahren war eine Image-Größe von mehreren Hundert Megabyte völlig normal: das Ubuntu-Image hatte 600 Megabyte, während das Microsoft .Net-Image einige Gigabyte wog. In jenen Tagen konnte der Download eines einzigen Images erhebliche Schäden an Ihrem freien Speicherplatz anrichten, selbst wenn Sie die Schichten zwischen den Images geteilt haben. Heute – Gottes Lob – wiegen die Images viel weniger, aber selbst dann können die vorhandenen Ressourcen schnell gefüllt werden, wenn keine Vorsichtsmaßnahmen getroffen werden.

Es gibt einige Arten von Images, die dem Endbenutzer direkt nicht sichtbar sind:

  • Intermediate-Images, auf deren Grundlage andere Images erstellt werden – sie können nicht gelöscht werden, wenn Sie Container verwenden, die auf diesen "anderen" Images basieren;
  • Dangling-Images – das sind solche Intermediate-Images, auf die keine laufenden Container verweisen – sie können gelöscht werden.
  • Mit dem folgenden Befehl können Sie überprüfen, ob sich dangling Images in Ihrem System befinden:

$ docker image ls -f dangling=true
REPOSITORY  TAG      IMAGE ID         CREATED             SIZE
none      none   21e658fe5351     vor 12 Minuten      71,3MB

Sie 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 entfernt alle nicht verwendeten Images.
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 recoupierter Speicherplatz: 12,9 kB

Wenn wir plötzlich alle Images (und nicht nur die nicht verwendeten) mit einem Befehl löschen möchten, können wir Folgendes tun:

$ docker image rm $(docker image ls -q)

Festplattennutzung durch Volumes

Volumes werden zum Speichern von Daten außerhalb des Container-Dateisystems verwendet. Zum Beispiel, wenn wir die Ergebnisse einer Anwendung speichern möchten, um sie später anderweitig zu verwenden. Ein häufiges Beispiel sind Datenbanken.

Lassen Sie uns einen MongoDB-Container starten, einem externen Volume zuweisen und eine Datenbanksicherung (die sich in der Datei bck.json befindet) 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 
  --jsonArray

Die Daten werden auf der Host-Maschine im Verzeichnis /var/lib/docker/volumes gespeichert. Warum nicht mit Schreib-Lese-Zugriff im Container? Weil im Dockerfile des MongoDB-Images das Verzeichnis /data/db (in dem MongoDB standardmäßig seine Daten speichert) als Volume definiert ist.

Docker Tipps: Reinigen Sie Ihre Maschine von unnötigem Ballast

Anmerkungen: Viele Images, aus denen Daten erstellt werden sollen, verwenden Volumes zur Speicherung dieser Daten.

Wenn wir mit MongoDB fertig sind und den Container stoppen (oder 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)

Alternativ können wir den bereits bekannten Unterbefehl prune verwenden:

$ docker volume prune
WARNUNG! Dies entfernt alle lokalen Volumes, die von mindestens einem Container nicht verwendet werden.
Sind Sie sicher, dass Sie fortfahren möchten? [y/N] y
Gelöschte Volumes:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da

Insgesamt wiedergewonnener Speicherplatz: 25,82 GB
luc@saturn:~$

Verwendung von Speicherplatz für den Cache beim Erstellen von Images

In Docker 18.09 hat sich der Prozess der Erstellung von Images dank des BuildKit-Tools etwas verändert. Mit diesem Tool wird die Geschwindigkeit des Prozesses erhöht und die Verwaltung von Datenspeicherung und Sicherheit optimiert. In diesem Beitrag werden wir nicht alle Details dieses bemerkenswerten Werkzeugs betrachten, sondern uns lediglich darauf konzentrieren, wie es sich auf den Umgang mit Speicherplatz auswirkt.

Angenommen, wir haben eine ganz einfache Node.Js-Anwendung:

  • Die Datei index.js startet einen einfachen HTTP-Server, der mit einer Zeichenkette auf jede empfangene Anfrage antwortet:
  • Die Datei package.json definiert die Abhängigkeiten; es wird nur expressjs zur Ausführung des HTTP-Servers verwendet:

$ 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(), 'Request erhalten'));
});
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 zur Erstellung 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 die herkömmliche Weise erstellen, ohne BuildKit zu verwenden:

$ docker build -t app:1.0 .

Wenn wir die Nutzung des Speicherplatzes überprüfen, sehen wir, dass nur das Basis-Image (node:13-alpine) und das finale Image (app:1.0) Speicher belegen:

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         0B

Jetzt erstellen wir die zweite Version unserer Anwendung, diesmal unter Verwendung von BuildKit. Dazu müssen wir nur die Umgebungsvariable DOCKER_BUILDKIT auf den Wert 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       RECLAIMABLE
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.949kB

Um ihn zu bereinigen, verwenden wir den folgenden Befehl:

$ docker builder prune
WARNING! This will remove all dangling build cache.
Are you sure you want to continue? [y/N] y
Deleted build cache objects:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi

Total reclaimed space: 8.949kB

Alles bereinigen!

Wir haben also die Bereinigung des Speicherplatzes, der von Containern, Images und Volumes belegt wird, betrachtet. Dabei hilft uns das Subteam prune. Es kann jedoch auch auf Systemebene von Docker verwendet werden und wird alles bereinigen, was möglich ist:

$ docker system prune
WARNUNG! Dies wird entfernen:
  - alle gestoppten Container
  - alle Netzwerke, die von mindestens einem Container nicht verwendet werden
  - alle nicht verwendeten Images
  - alle nicht verwendeten Build-Caches

Sind Sie sicher, dass Sie fortfahren möchten? [y/N]

Wenn Sie aus irgendeinem Grund Speicherplatz auf einer Docker-Maschine sparen, sollten Sie sich angewöhnen, diesen Befehl regelmäßig auszuführen.

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster