10 Punkte von GN⁺ 2024-01-09 | 1 Kommentare | Auf WhatsApp teilen
  • Dive ist ein Tool zum Untersuchen von Layern und Datei-Inhalten in Docker-/OCI-Images und zum Auffinden von Potenzial zur Reduzierung der Image-Größe
  • Mit Image-Tag, ID oder Digest kann dive <your-image-tag> ausgeführt werden, oder mit dive build -t <some-tag>. lässt sich die Analyse direkt nach dem Build in einem Schritt durchführen
  • Wenn ein Layer ausgewählt wird, zeigt das Tool den zusammengeführten Dateibaum dieses Layers und der vorherigen Layer an; hinzugefügte, geänderte und gelöschte Dateien sowie kumulierte Änderungen lassen sich im Dateibaum prüfen
  • Die experimentelle Kennzahl image efficiency schätzt verschwendeten Speicherplatz durch doppelte Dateien, Datei-Verschiebungen zwischen Layern und nicht vollständig entfernte Dateien als Score und Gesamtgröße
  • Mit CI=true kann die UI übersprungen werden; anhand von Image-Effizienz und verschwendetem Speicherplatz wird ein Pass/Fail-Ergebnis zurückgegeben, sodass sich die Kontrolle der Image-Größe in CI-Pipelines automatisieren lässt

Was Dive macht

  • Dive ist ein Tool zum Untersuchen von Docker-Images, Layer-Inhalten und Möglichkeiten zur Verringerung der Größe von Docker-/OCI-Images
  • Die Standardausführung übergibt ein Image-Tag, eine ID oder einen Digest
    • dive <your-image-tag>
  • Die Ausführung ist auch als Docker-Container möglich; dabei muss der Docker-Socket gemountet werden
    • Verwendung des Images docker.io/wagoodman/dive
    • Als Beispiel-Zielimage wird nginx:latest genannt
  • Wenn ein Image direkt nach dem Build analysiert werden soll, kann statt docker build der gleich aufgebaute Befehl dive build verwendet werden
    • dive build -t <some-tag> .
  • Unter macOS unterstützt die als Container ausgeführte Build-Analyse nur die Docker Container Engine
  • Der Projektstatus ist beta quality; neue Feature-Anfragen oder Bugs können als Issues eingereicht werden

Layer und Dateiänderungen untersuchen

  • Wird links ein Layer ausgewählt, erscheint rechts der Dateibaum, der diesen Layer und die vorherigen Layer zusammenführt
  • Der Dateibaum kann mit den Pfeiltasten durchsucht werden
  • Der Status von in jedem Layer geänderten Dateien wird im Dateibaum angezeigt
    • geändert
    • modifiziert
    • hinzugefügt
    • entfernt
  • Die Änderungsanzeige kann entweder relativ zu einem bestimmten Layer oder als kumulierte Änderungen bis zu diesem Layer angepasst werden

Image-Effizienz und Schätzung des verschwendeten Speicherplatzes

  • Das Panel unten links zeigt grundlegende Layer-Informationen und die experimentelle Kennzahl image efficiency an
  • Diese Kennzahl schätzt verschwendeten Speicherplatz im Image
    • doppelte Dateien zwischen Layern
    • Datei-Verschiebungen zwischen Layern
    • nicht vollständig entfernte Dateien
  • Das Ergebnis wird als prozentualer Score und als gesamter verschwendeter Dateispeicherplatz ausgegeben

Verwendung in CI als Pass/Fail-Kriterium

  • Bei Ausführung mit der Umgebungsvariablen CI=true überspringt Dive die UI, analysiert das Image und liefert das Pass/Fail-Ergebnis über den Rückgabecode
  • In der Datei .dive-ci im Repository-Root lassen sich drei Kriterien festlegen
    • lowestEfficiency: schlägt fehl, wenn die Effizienz unter dem angegebenen Wert liegt
    • highestWastedBytes: schlägt fehl, wenn der verschwendete Speicherplatz die angegebene Größe erreicht oder überschreitet
    • highestUserWastedPercent: schlägt fehl, wenn der Verschwendungsanteil bezogen auf User-Layer den angegebenen Wert erreicht oder überschreitet
  • Bei der Berechnung von highestUserWastedPercent wird der base image layer nicht in die Gesamtgröße des Images einbezogen
  • Der Pfad zur CI-Konfigurationsdatei kann mit der Option --ci-config überschrieben werden

Image-Quellen und Container-Engines

  • Mit der Option --source kann ausgewählt werden, von wo das Container-Image geladen wird
    • dive <your-image> --source <source>
    • dive <source>://<your-image>
  • Unterstützte source-Optionen sind:
    • docker: Docker engine, Standardwert
    • docker-archive: Docker Tar Archive auf dem Datenträger
    • podman: Podman engine, nur unter Linux unterstützt

Installation und Ausführungsarten

  • Unter Ubuntu/Debian kann die Installation per .deb-Paket oder Snap erfolgen
  • Bei der Snap-Variante wird gewarnt, wenn Docker per apt-get installiert wurde; sie wird nicht empfohlen, da der bestehende Docker-Daemon beschädigt werden kann
  • Unter RHEL/Centos ist die Installation per .rpm-Paket möglich
  • Für Arch Linux ist das Paket im extra repository verfügbar und kann mit pacman installiert werden
  • Unter macOS kann die Installation über Homebrew, MacPorts oder über den Darwin-Build auf der releases page erfolgen
  • Unter Windows kann die Installation über Chocolatey, scoop, winget oder über den Windows-Build auf der releases page erfolgen
  • Für die Installation als Go-Tool wird Go 1.10 oder höher benötigt
    • go install github.com/wagoodman/dive@latest
    • Bei Installation auf diesem Weg wird bei dive -v nicht die korrekte Version angezeigt
  • Es werden auch Installationswege für Nix/NixOS und x-cmd angeboten
  • Bei der Ausführung als Docker-Image muss die Docker-Socket-Datei eingebunden werden
    • -v /var/run/docker.sock:/var/run/docker.sock
  • Je nach lokaler Docker-Version kann eine Umgebungsvariable wie DOCKER_API_VERSION=1.37 erforderlich sein
  • Bei alternativen Laufzeitumgebungen wie Colima muss möglicherweise die Umgebungsvariable DOCKER_HOST gesetzt werden, um lokale Images zu laden

Bedienung und UI-Einstellungen

  • Wichtige Tastenkürzel dienen zum Wechseln zwischen Layer-Ansicht und Dateibaum-Ansicht sowie für Navigation, Filterung und Anzeigeumschaltung
    • Ctrl+C oder Q: Beenden
    • Tab: zwischen Layer-Ansicht und Dateibaum-Ansicht wechseln
    • Ctrl+F: Dateifilter
    • Ctrl+A: in der Layer-Ansicht Anzeige kumulierter Image-Änderungen, in der Dateibaum-Ansicht Umschalten der Anzeige hinzugefügter Dateien
    • Ctrl+L: Änderungen des aktuellen Layers anzeigen
    • Ctrl+R, Ctrl+M, Ctrl+U: Anzeige entfernter, modifizierter bzw. unveränderter Dateien umschalten
    • Ctrl+B: Anzeige von Dateiattributen umschalten
  • Eine separate Konfiguration ist nicht erforderlich, Werte können aber mit einer YAML-Konfigurationsdatei überschrieben werden
  • Zu den konfigurierbaren Punkten gehören Container-Engine, Ignorieren von Parsing-Fehlern bei Image-Archiven, Logging, Tastenkürzel, Diff-Anzeige, Breite des Dateibaums, standardmäßig eingeklappter Verzeichniszustand und Anzeige kumulierter Layer-Änderungen
  • Nach Konfigurationsdateien wird an folgenden Orten gesucht
    • $XDG_CONFIG_HOME/dive/*.yaml
    • $XDG_CONFIG_DIRS/dive/*.yaml
    • ~/.config/dive/*.yaml
    • ~/.dive.yaml
  • Anstelle von .yaml kann auch die Erweiterung .yml verwendet werden

1 Kommentare

 
GN⁺ 2024-01-09
Hacker-News-Kommentare
  • Beim Umgang mit Images und Layern ist crane hervorragend, und auch die zugrunde liegende Bibliothek go-containerregistry ist gut.
    Man kann einem bestehenden Image neue Layer hinzufügen oder Metadaten (env vars, labels, entrypoint usw.) ändern, und man kann Images mit mehreren Layern auch zu einem einzelnen Layer „flatten“.
    Außerdem ist ein „Rebase“ möglich, bei dem Änderungen erneut auf ein neues Base-Image angewendet werden; all diese Vorgänge laufen direkt in der Registry ab, sodass Docker nicht nötig ist.
    https://github.com/google/go-containerregistry/blob/main/cmd...

    • Gute Empfehlung. Anders als Docker funktioniert crane ohne root und ohne Daemon, was es für Nix gut geeignet macht; im Nix-Repository ist es ebenfalls unter dem Namen crane verfügbar.
      Dadurch kann man mit Nix nicht nur Build-Abhängigkeiten (z. B. Go), sondern auch Werkzeuge für Packaging und Deployment (z. B. gnu tar, crane) gemeinsam verwalten.
    • Ich frage mich, ob eine geringere Anzahl von Layern Performance-Vorteile bringt. Soweit ich es verstehe, bleibt die Gesamtgröße beim Zusammenführen von Images gleich, daher bringt die Layer-Zusammenführung an sich keinen Nutzen.
  • dive war wirklich nützlich, um zu verstehen, wie Docker-Images funktionieren und wie man ein effizientes Dockerfile schreibt.
    Dokumentation zu lesen ist ebenfalls wichtig, aber direkt zu sehen, wie sich die resultierende Layer-Struktur nach Änderungen am Dockerfile verändert, war entscheidend für das Verständnis.

  • Dive ist großartig. Solche Tools sind wichtig, um zu lernen und sicher zu sein, was genau ich baue und ausrolle.
    Dredge ist ebenfalls einen Blick wert; ich nutze es, um Layer-Unterschiede zu vergleichen.
    https://github.com/mthalman/dredge/blob/main/docs/commands/i...

  • Vielleicht eine dumme Frage, aber ich frage mich, warum die meisten Container- und Infrastruktur-Tools in Go geschrieben sind.
    Mir fallen Docker, Podman, nerdctl, Terraform und Kubernetes ein; ich würde gern wissen, ob Go beim Bau solcher Tools klare Vorteile bietet.

    • Zu Docker kann ich etwas sagen. Der erste Prototyp war in Python geschrieben, und auch das Unternehmen war stark Python-orientiert.
      Der Hauptgrund für die Neufassung in Go war, auf die damals (2012) wachsende Popularität von Go aufzuspringen. Ich war dabei.
    • Go ist die Sprache, mit der Cross-Compilation und Deployment am einfachsten sind; sie bietet sehr gute Performance im Verhältnis zur Produktivität, gute eingebaute Nebenläufigkeit und hervorragende Networking-Funktionen in der Standardbibliothek.
      Wenn man sich vorstellt, Docker und Kubernetes wären in anderen populären Sprachen geschrieben, wird der Unterschied deutlich.
    • System-Tools, Utilities, Command-Line-Tools und Netzwerksoftware sind meiner Ansicht nach die Bereiche, in denen Go am stärksten glänzt.
      Als ausgereifte moderne Alternative scheint es im Grunde nur Rust zu geben.
    • Kubernetes ist in Go geschrieben, weil Google Go entwickelt hat und auch Kubernetes entwickelt hat.
      Aus demselben Grund gibt es in den internen Teams viele Go-Engineers.
    • Wenn man Container ausführt, möchte man sich möglichst wenig um das zugrunde liegende System kümmern, und Go macht es einfach, in seiner eigenen kleinen Welt zu laufen.
      Dazu kommt der Ökosystem-Effekt: Man kann Pakete anderer Implementierungen direkt in Teilen des eigenen Codes nutzen.
  • Ich mag Dive und hole es mehrmals im Monat aus meinem Werkzeugkasten.
    Allerdings frage ich mich, ob es eine Möglichkeit gibt, den Inhalt der ausgewählten Datei direkt anzusehen. Oft möchte ich prüfen, ob eine Datei in einem Layer existiert, und mir dann ihren Inhalt ansehen; derzeit starte ich dafür meist einen Container und verwende cat oder extrahiere den Inhalt und navigiere dann in den Ordner.

    • Mit etwas Geschick kann man per rsync auf die Datei zugreifen, aber das unterscheidet sich nicht wesentlich von der Verwendung von cat.
  • Beim Erweitern mehrerer öffentlicher Docker-Container hat mich Dive mehrfach gerettet, wenn ich herausfinden musste, was darin vor sich geht.
    Wirklich Software der Klasse A+.

  • Es gibt noch weitere großartige Terminal-TUI-Tools wie dive. Mir fallen lazydocker und dry ein.
    Auch im Docker-Bereich gibt es einige.
    [0] https://terminaltrove.com/

    • Lazydocker hat eine ähnliche, aber einfachere Funktion.
      Beim Nachsehen zeigte sich: Man kann die Layer sehen, aber es werden nur die Befehle der jeweiligen Layer angezeigt.
  • Dive ist ein erstaunliches Tool im Container-/Docker-Bereich. Es macht das Debugging dessen, was tatsächlich in einem Container steckt, viel einfacher.
    Als wir Depot [0] gestartet haben, wurden wir oft gefragt, wie man Image-Größen reduziert und Builds schneller macht; deshalb habe ich in einem kurzen Beitrag [1] zusammengefasst, wie man dieses Problem mit Dive angeht. Er könnte inzwischen etwas älter sein, aber vielleicht hilft er jemandem.
    Inspiriert von Dive haben wir außerdem sichtbarer gemacht, was bei jedem Build tatsächlich im Build-Kontext enthalten ist, und das vor ein paar Wochen als Depot-Feature veröffentlicht.
    [0] https://depot.dev
    [1] https://depot.dev/blog/reducing-image-size-with-dive
    [2] https://depot.dev/blog/build-context

  • Neben seiner großen Nützlichkeit hat Dive noch einen unterschätzten Vorteil: Der Autor ist ein hervorragender Entwickler und ein wirklich angenehmer Mensch, mit dem man gern zusammenarbeitet.

  • Auch Googles Tool container-diff ist wirklich nützlich.
    Ich verwende es, um zu prüfen, was ein beliebiges Skript, das zur Ausführung per Pipe in bash empfohlen wird, mit dem System machen würde.

    • Etwas weniger direkt mit allgemeinen Container-Utilities verwandt, aber ich nutze GoogleContainerTools/container-structure-test intensiv.
      Es ist eine praktische Möglichkeit, Integrationstests für Container-Apps oder Images auszuführen.
      Es ist schade, dass diese Open-Source-Projekte von Google offenbar Aufmerksamkeit brauchen, weil viele der ursprünglichen Maintainer weitergezogen sind. Wenn möglich, schicke ich PRs und schließe gelegentlich Issues. Gerade dieses Test-Tool ist äußerst wertvoll, um bei den vielen intern zu pflegenden Base-Images den Überblick zu behalten.