Tiefer Einstieg in Docker Images
James Reed
Infrastructure Engineer · Leapcell

Tiefgehende Analyse von Docker Images
I. Überblick über Docker Images
Als Grundlage von Containern repräsentieren Docker Images im Wesentlichen den Inhalt des Dateisystems des Containers. Es ist eine schreibgeschützte Vorlage, die zum Erstellen von Docker-Containern verwendet wird. Aus technischer Sicht verwenden Docker-Images ein geschichtetes Strukturdesign. Mit Ausnahme des Basis-Images werden andere Images durch Überlagern neuer Inhalte auf vorhandene Images generiert. Die Metadaten jeder Ebene des Images werden in einer json
-Datei gespeichert. Diese Metadaten beschreiben nicht nur den statischen Inhalt des Dateisystems, sondern enthalten auch dynamische Dateninformationen, wie z. B. die Erstellungszeit des Images, Builder-Anweisungen usw.
1.1 Erstellen von Docker Images
Docker-Images werden normalerweise durch ein Dockerfile
erstellt. Ein Dockerfile
ist eine Textdatei, die eine Reihe von Anweisungen zum Definieren der Basisumgebung des Images, zum Installieren von Softwarepaketen, zum Kopieren von Dateien und für andere Operationen enthält. Während des Erstellungsprozesses erstellt Docker jede Ebene des Images Schritt für Schritt gemäß der Reihenfolge der Anweisungen im Dockerfile
. Wenn jede Anweisung ausgeführt wird, wird eine neue Image-Ebene generiert, und diese Ebenen werden für die Wiederverwendung in nachfolgenden Builds zwischengespeichert.
1.2 Methoden zur Verbesserung der Effizienz beim Erstellen von Images
- Rationale Nutzung des Caching-Mechanismus: Beim Erstellen eines Images prüft Docker, ob die von der aktuellen Anweisung generierte Image-Ebene bereits im lokalen Cache vorhanden ist. Wenn es vorhanden ist und bestimmte Bedingungen erfüllt (z. B. dieselbe Anweisung, unveränderter Dateiinhalte usw.), wird die zwischengespeicherte Image-Ebene direkt verwendet, um wiederholtes Erstellen zu vermeiden. Wenn beispielsweise die
RUN
-Anweisung ausgeführt wird, wird die Image-Ebene wiederverwendet, wenn das Ausführungsergebnis dieser Anweisung mit dem zuvor zwischengespeicherten Ergebnis übereinstimmt (beurteilt durch Vergleichen der Anweisung und Änderungen im Dateisystem usw.). - Optimieren der Struktur des Dockerfile: Platzieren Sie die Anweisungen, die sich nicht häufig ändern (z. B. die Installation grundlegender Softwarepakete), an den Anfang. Auf diese Weise können die vorhandenen Image-Ebenen wiederverwendet werden, wenn das
Dockerfile
später geändert wird, solange diese grundlegenden Anweisungen unverändert bleiben, wodurch die Erstellungszeit verkürzt wird. - Erstellen in Ebenen: Teilen Sie den komplexen Erstellungsprozess in mehrere Phasen auf, und jede Phase ist nur für eine bestimmte Aufgabe verantwortlich. Wenn Sie beispielsweise ein Image erstellen, das einen Kompilierungsprozess enthält, kann die Kompilierung zuerst in einer Phase abgeschlossen werden, und dann kann das kompilierte Ergebnis in einer anderen Phase in das endgültige Image kopiert werden, wodurch die Größe des endgültigen Images reduziert werden kann.
II. Befehle im Zusammenhang mit Docker Images
Der Docker-Client bietet eine umfangreiche Reihe von Befehlen zur Interaktion mit dem Docker-Daemon, um verschiedene Aufgaben im Zusammenhang mit Images auszuführen:
- Auflisten von Images: Der Befehl
docker images
wird verwendet, um alle Images auf dem Docker-Host aufzulisten. Sie können den Parameter-f
zum Filtern verwenden. Beispielsweise kanndocker images -f dangling=true
alle Images ohne Tags auflisten. - Erstellen von Images: Der Befehl
docker build
erstellt ein neues Image aus einemDockerfile
. Zum Beispieldocker build -t myimage:latest.
, wobei-t
verwendet wird, um das Tag des Images anzugeben, und.
gibt dasDockerfile
im aktuellen Verzeichnis an. - Anzeigen des Image-Verlaufs: Der Befehl
docker history
kann den Build-Verlauf eines bestimmten Images auflisten und Informationen wie die Erstellungszeit jeder Ebene des Images, die ausgeführten Anweisungen und die Größe des Images anzeigen. - Importieren von Images: Der Befehl
docker import
erstellt ein neues Dateisystem-Image aus einerTarball
-Datei. - Pull Images: Der Befehl
docker pull
zieht das angegebene Image aus der Docker Image Registry auf den lokalen Rechner. - Push Images: Der Befehl
docker push
überträgt das lokale Image in die angegebene Image Registry. - Löschen von Images: Der Befehl
docker rmi
wird zum Löschen lokaler Images verwendet. Wenn ein Image von mehreren Tags referenziert wird, müssen Sie zuerst alle Tags entfernen oder den Parameter-f
verwenden, um das Löschen zu erzwingen. - Speichern von Images: Der Befehl
docker save
speichert das Image alstar
-Datei, was für die Migration des Images in verschiedenen Umgebungen praktisch ist. - Suchen von Images: Der Befehl
docker search
sucht auf Docker Hub nach Images, die die Bedingungen erfüllen. - Tag Images: Der Befehl
docker tag
versieht das Image mit Tags, was für die Versionsverwaltung und Identifizierung des Images praktisch ist.
III. Der Download-Prozess von Docker Images (Pull-Operation)
Docker verwendet eine typische C/S-Architektur (Client/Server). Client-Befehle wie docker pull
werden schließlich zur Verarbeitung an den Docker-Daemon (Serverseite) gesendet. Wenn docker pull
ausgeführt wird, läuft der spezifische Prozess wie folgt ab:
- Der Docker-Client organisiert die Konfiguration und Parameter und sendet die
pull
-Anweisung an den Docker-Server. - Nachdem die Serverseite die Anweisung empfangen hat, übergibt sie sie an den entsprechenden Handler. Der Handler startet eine
CmdPull
-Aufgabe, die beim Starten des Docker-Daemons registriert wurde. - Entsprechend der eingehenden Image Registry-Adresse (Registry Address), dem Repository-Namen (Repo Name), dem Image-Namen und dem Tag (Tag) findet und lädt der Docker-Daemon das Image durch die folgenden Schritte herunter:
- Abrufen aller Image-IDs unter dem Repository: Über die Schnittstelle
GET /repositories/{repo}/images
. - Abrufen der Informationen aller Tags unter dem Repository: Über die Schnittstelle
GET /repositories/{repo}/tags
. - Suchen Sie die entsprechende Image-UUID anhand des Tags und laden Sie das Image herunter.
- Abrufen der historischen Informationen des Images und Herunterladen dieser Image-Ebenen einzeln: Über die Schnittstelle
GET /images/{image_id}/ancestry
. Wenn die Image-Ebene bereits lokal vorhanden ist, wird der Download übersprungen. Andernfalls wird der Download fortgesetzt. - Abrufen der
json
-Informationen der Image-Ebene: Über die SchnittstelleGET /images/{image_id}/json
. - Herunterladen des Image-Inhalts: Über die Schnittstelle
GET /images/{image_id}/layer
.
- Abrufen aller Image-IDs unter dem Repository: Über die Schnittstelle
- Nach Abschluss des Downloads wird der Image-Inhalt im lokalen UnionFS (Union File System) gespeichert und die Informationen des neu heruntergeladenen Images werden dem TagStore hinzugefügt.
IV. Speicherung von Docker Images
4.1 UnionFS und aufs
UnionFS ist die Grundlage für Docker zur Implementierung hierarchischer Images. Es ist ein Dateisystemdienst, der das transparente Überlagern mehrerer Zweige von Dateisystemen auf Systemen wie Linux, FreeBSD und NetBSD unterstützt, um ein einheitliches Dateisystem zu bilden. In Docker werden Images in einer geschichteten Form gespeichert. Die Anwendungsschicht sieht ein vollständiges Dateisystem, während die darunter liegende Schicht den Inhalt und die Beziehungen jeder Image-Schicht über UnionFS verwaltet.
aufs
(Another UnionFS) ist einer der häufig verwendeten Speichertreiber in Docker. Darüber hinaus gibt es devicemapper
und andere. Benutzer können einen geeigneten Speichertreiber entsprechend ihren Anforderungen auswählen oder sogar ihren eigenen Treiber implementieren.
4.2 Die Speicherstruktur von aufs Images
Nehmen Sie das Image ubuntu:20.04
als Beispiel (vorausgesetzt, die aktuelle Docker-Version ist 20.10.0 und der Image-Treiber ist aufs
), verwenden Sie docker history
, um den Image-Verlauf anzuzeigen:
$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE myregistry/ubuntu 20.04 8b24f7a1cb23 2 months ago 256.3 MB $ docker history 8b24 IMAGE CREATED CREATED BY SIZE 8b24f7a1cb23 2 months ago /bin/sh -c #(nop) CMD ["bash"] 0 B b17ee223aa89 2 months ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.9 kB c18294cc5170 2 months ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 195.5 kB d4fd76b09ce9 2 months ago /bin/sh -c #(nop) ADD file:0018ff77d038472f52 256.1 MB 511136ea3c5a 3 years ago 0 B
Es ist ersichtlich, dass das Image ubuntu:20.04
mehrere Ebenen enthält. Die aufs
-Daten werden im Verzeichnis /var/lib/docker/aufs
gespeichert, das drei Hauptordner enthält:
- layers: Zeichnet auf, aus welchen Ebenen jedes Image besteht.
- diff: Speichert den Unterschied zwischen jedem Image und dem vorherigen Image, d. h. die tatsächlichen Daten der aktuellen Image-Ebene.
- mnt: Als Mount-Punkt, der von UnionFS nach außen bereitgestellt wird, hat jeder laufende Container einen entsprechenden Ordner in diesem Verzeichnis, der verwendet wird, um eine einheitliche Dateizugriffsschnittstelle bereitzustellen.
Darüber hinaus speichert Docker die Metadaten auch im json
-Format für jede Image-Ebene, die in /var/lib/docker/graph/<image_id>/json
gespeichert wird, zum Beispiel:
{ "id": "8b24f7a1cb23146e20erewtewtertewrwc0f82943f4ab8c097e7", "parent": "b17ee223aa89d1b136ea55eqweqweqwrewra6c88d93e1ad7c", "created": "2024-12-21T02:11:06.735146646Z", "container": "c9a3eda5951d28aa8dbe5qwrqwrewrtw886d0a8e7a710132a38ec", "container_config": { "Hostname": "43bd710ec89a", "Domainname": "", "User": "", "Memory": 0, "MemorySwap": 0, "CpuShares": 0, "Cpuset": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "PortSpecs": null, "ExposedPorts": null, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) CMD [\"bash\"]" ], "Image": "b17ee223aa89d1b136ea55e4421f4ce413dfc6c0cc6b2186dea6c88d93e1ad7c", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "NetworkDisabled": false, "MacAddress": "", "OnBuild": [], "Labels": null }, "docker_version": "20.10.0", "config": { "Hostname": "43bd710ec89a", "Domainname": "", "User": "", "Memory": 0, "MemorySwap": 0, "CpuShares": 0, "Cpuset": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "PortSpecs": null, "ExposedPorts": null, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "bash" ], "Image": "b17ee223aa89qwrewtretgertwerewrq6dea6c88d93e1ad7c", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "NetworkDisabled": false, "MacAddress": "", "OnBuild": [], "Labels": null }, "architecture": "amd64", "os": "linux", "Size": 0 }
Gleichzeitig speichert die Datei /var/lib/docker/graph/<image_id>/layersize
die Größeninformationen der Image-Ebene.
V. Der Erstellungs- und Caching-Mechanismus von Docker Images
Wenn Sie docker build
zum Erstellen eines Images verwenden, verwendet Docker den Caching-Mechanismus, um die Erstellungseffizienz zu verbessern. Nehmen Sie das folgende Dockerfile
als Beispiel:
FROM ubuntu:20.04 RUN apt-get update ADD run.sh / VOLUME /data CMD ["./run.sh"]
Während des Erstellungsprozesses wird Docker gemäß der Reihenfolge der Anweisungen ausgeführt:
- Verarbeiten der
FROM
-Anweisung: Der Docker-Daemon sucht zuerst lokal nach dem Imageubuntu:20.04
. Wenn es nicht vorhanden ist, wird es aus der Image Registry gezogen und seinejson
-Datei mit Metadaten abgerufen. - Verarbeiten der
RUN
-Anweisung: Wenn kein Cache verfügbar ist, führt diese Anweisungapt-get update
aus, und die Änderungen im Dateisystem (z. B. die aktualisierte Softwarepaketliste usw.) werden im Verzeichnis/var/lib/docker/aufs/diff/<image_id>/
gespeichert. Gleichzeitig zeichnet das Feldcontainer_config.Cmd
in derjson
-Datei die ausgeführte Anweisung auf. Wenn das nächste Mal erstellt wird, wenn dasparent
der neuen Image-Ebene immer nochubuntu:20.04
ist und der Inhalt, der imcmd
derjson
-Datei geändert werden soll, derselbe ist, wird davon ausgegangen, dass die Image-Ebenen identisch sind, und sie werden direkt wiederverwendet, ohne dass sie neu erstellt werden müssen. - Verarbeiten der
ADD
- undCOPY
-Anweisungen: Für die BefehleADD
oderCOPY
bestimmt Docker, ob die Images identisch sind, indem es den Hashwert der Datei berechnet. In derjson
-Datei zeichnet das FeldCmd
, das derADD
-Anweisung entspricht, die Hash-Zeichenfolge der Datei auf. Die Image-Ebene wird nur dann wiederverwendet, wenn der Dateiinhalt, der Dateiname usw. vollständig identisch sind.
Allerdings hat der Caching-Mechanismus Einschränkungen. Für Befehle, die auf externe Ressourcen angewiesen sind (wie z. B. apt-get update
, um Updates von externen Softwarequellen abzurufen, curl
, um externe Dateien herunterzuladen usw.), kann Docker die Änderungen externer Inhalte nicht automatisch erkennen. Zu diesem Zeitpunkt können Sie den Parameter --no-cache
verwenden, um die Deaktivierung des Caches zu erzwingen und das Image neu zu erstellen. Daher müssen Entwickler beim Schreiben eines Dockerfile
den Caching-Mechanismus vollständig berücksichtigen und die von den offiziellen Stellen bereitgestellten Best Practices befolgen, um die Richtigkeit und Effizienz der Image-Erstellung sicherzustellen.
VI. Die Beziehung zwischen Docker Images und Containern
Docker-Container sind laufende Instanzen von Images. Images enthalten statischen Dateisysteminhalt, und Container fügen auf dieser Basis dynamische Laufzeitzustände hinzu. Die relevanten Informationen während der Ausführung des Containers (mit Ausnahme des Inhalts des Dateisystems) werden in der json
-Datei des Images gespeichert. Zum Beispiel:
- Umgebungsvariablen: Wie z. B.
ENV FOO=BAR
, das die Umgebungsvariablen während der Ausführung des Containers definiert. - Datenvolumen: Die durch
VOLUME /some/path
deklarierten Container-Datenvolumen werden während der Ausführung des Containers dynamisch hinzugefügt und sind nicht der feste Inhalt der Image-Ebene. - Freigegebene Ports:
EXPOSE 80
zeichnet die Ports auf, die der Container während der Ausführung nach außen freigeben muss. - Ausführungseinstiegspunkt:
CMD ["./myscript.sh"]
definiert den Befehl, der beim Starten des Containers ausgeführt werden soll.
Beim Starten eines Containers liest der Docker-Daemon die Image-Informationen als Root-Dateisystem (rootfs) des Containers und liest gleichzeitig die dynamischen Informationen in der json
-Datei, um den Laufzeitzustand des Containers zu konfigurieren. Jeder laufende Container ist ein Kindprozess des Docker-Daemons, und der Docker-Daemon ist für die Verwaltung des Lebenszyklus und der Ressourcenzuweisung des Containers verantwortlich.
VII. Löschen von Docker Images
Images werden lokal im UnionFS-Format gespeichert, und der Befehl docker rmi
kann zum Löschen von Images verwendet werden. Beim Löschen sind folgende Punkte zu beachten:
- Image-Referenzbeziehung: Es gibt ein Konzept der "Referenz" für Images, d. h. ein Image kann von mehreren Tags referenziert werden. Beim Löschen eines Images mit Tags werden die Tags zuerst entfernt (Untag-Operation). Wenn das Image weiterhin von anderen Tags referenziert wird, müssen zuerst alle Tags gelöscht werden, oder der Parameter
-f
kann verwendet werden, um das Löschen zu erzwingen. - Löschen von mehrschichtigen Images: Wenn ein Image mehrere Ebenen enthält und die mittleren Ebenen nicht von anderen Images referenziert werden, werden beim Löschen dieses Images alle nicht referenzierten Image-Ebenen zusammen gelöscht.
Leapcell: Das Beste von Serverless Web Hosting
Abschließend möchte ich eine Plattform empfehlen, die sich am besten für die Bereitstellung von Webdiensten eignet: Leapcell
🚀 Erstellen Sie mit Ihrer Lieblingssprache
Entwickeln Sie mühelos in JavaScript, Python, Go oder Rust.
🌍 Stellen Sie unbegrenzt viele Projekte kostenlos bereit
Zahlen Sie nur für das, was Sie verwenden – keine Anfragen, keine Gebühren.
⚡ Pay-as-You-Go, keine versteckten Kosten
Keine Leerlaufgebühren, nur nahtlose Skalierbarkeit.
📖 Entdecken Sie unsere Dokumentation
🔹 Folgen Sie uns auf Twitter: @LeapcellHQ