Arbeiten mit Docker-Images

DockerBeginner
Jetzt üben

Einführung

In diesem Lab werden wir Docker-Images untersuchen, die das Fundament für das Erstellen und Ausführen von Containern bilden. Wir werden lernen, wie man Images aus dem Docker Hub abruft, Container mit verschiedenen Image-Versionen ausführt, Images auflistet und entfernt, das Konzept der Image-Layer versteht, nach Images sucht und grundlegendes Tagging durchführt. Diese praktische Erfahrung vermittelt Ihnen die wesentlichen Fähigkeiten für einen effektiven Umgang mit Docker-Images. Keine Sorge, falls Sie neu bei Docker sind – wir führen Sie mit detaillierten Erklärungen durch jeden Schritt.

Dies ist ein Guided Lab, das Schritt-für-Schritt-Anleitungen bietet, um Ihnen beim Lernen und Üben zu helfen. Folgen Sie den Anweisungen sorgfältig, um jeden Schritt abzuschließen und praktische Erfahrung zu sammeln. Historische Daten zeigen, dass dies ein Lab für Anfänger mit einer Abschlussquote von 90% ist. Es hat eine positive Bewertungsrate von 99% von Lernenden erhalten.

Images aus dem Docker Hub abrufen

Der Docker Hub ist ein öffentliches Repository für Docker-Images, vergleichbar mit GitHub für Quellcode. Hier finden Sie vorgefertigte Images für viele gängige Softwareanwendungen und Betriebssysteme. Beginnen wir damit, das offizielle Nginx-Image abzurufen (zu "pullen").

Öffnen Sie ein Terminal auf Ihrem System. Sie sollten eine Eingabeaufforderung sehen, die etwa so aussieht:

labex:project/ $

Lassen Sie uns nun das Nginx-Image abrufen. Geben Sie den folgenden Befehl ein und drücken Sie die Eingabetaste:

docker pull nginx

Dieser Befehl weist Docker an, die neueste Version des Nginx-Images aus dem Docker Hub herunterzuladen. Sie sollten eine Ausgabe ähnlich dieser sehen:

Using default tag: latest
latest: Pulling from library/nginx
5040bd298390: Pull complete
d7a91cdb22f0: Pull complete
9cac4850e5df: Pull complete
Digest: sha256:33ff28a2763feccc1e1071a97960b7fef714d6e17e2d0ff573b74825d0049303
Status: Downloaded newer image for nginx:latest

Lassen Sie uns analysieren, was hier passiert:

  1. "Using default tag: latest" – Wenn Sie keine Version angeben, geht Docker davon aus, dass Sie die aktuellste Version wünschen.
  2. Die nächsten Zeilen zeigen, wie Docker verschiedene "Layer" (Schichten) des Images herunterlädt. Jeder Layer repräsentiert eine Reihe von Änderungen am Dateisystem.
  3. Der "Digest" ist eine eindeutige Kennung für genau diese Version des Images.
  4. Die letzte Zeile bestätigt, dass das Image erfolgreich heruntergeladen wurde.

Nachdem wir das Image heruntergeladen haben, überprüfen wir, ob es sich auf unserem System befindet. Dazu listen wir alle lokal vorhandenen Docker-Images auf:

docker images

Sie sollten eine Ausgabe ähnlich dieser sehen:

REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
nginx         latest    605c77e624dd   2 weeks ago    141MB

Dies zeigt uns:

  • REPOSITORY: Der Name des Images (nginx)
  • TAG: Die Version des Images (latest)
  • IMAGE ID: Eine eindeutige Kennung für dieses Image
  • CREATED: Wann diese Version des Images erstellt wurde
  • SIZE: Wie viel Speicherplatz das Image auf der Festplatte belegt

Machen Sie sich keine Sorgen, wenn die genauen Zahlen abweichen – wichtig ist, dass ein Eintrag für nginx erscheint.

Falls Sie neugierig sind, welche anderen Images sich auf Ihrem System befinden: Möglicherweise sehen Sie Einträge für "jenkins/jenkins" oder "gcr.io/k8s-minikube/kicbase". Dies sind vorinstallierte Images, die wir in diesem Lab nicht verwenden werden.

Verschiedene Versionen eines Images ausführen

Docker ermöglicht es Ihnen, spezifische Versionen eines Images mithilfe von Tags auszuführen. Tags fungieren als Aliase für bestimmte Versionen. Lassen Sie uns dieses Konzept am Beispiel des Python-Images untersuchen.

Zuerst rufen wir das neueste Python-Image ab:

docker pull python

Sie sehen eine ähnliche Ausgabe wie beim Nginx-Image. Hier wird die aktuellste Python-Version heruntergeladen.

Nun rufen wir eine ganz bestimmte Version von Python ab, zum Beispiel die Version 3.7:

docker pull python:3.7

Beachten Sie, dass wir :3.7 an python angehängt haben. Dies weist Docker an, gezielt die Version 3.7 abzurufen anstatt der neuesten Version.

Listen wir unsere Python-Images auf, um die verschiedenen Versionen zu sehen:

docker images python

Die Ausgabe sollte etwa so aussehen:

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
python       3.7       1f1a7b570fbd   2 weeks ago    907MB
python       latest    98ccd1643c71   2 weeks ago    920MB

Wir haben nun zwei Python-Images: eines mit dem Tag latest (was je nach Zeitpunkt des Labs Python 3.9 oder 3.10 sein kann) und eines mit dem Tag 3.7.

Lassen Sie uns Container mit diesen verschiedenen Versionen ausführen, um den Unterschied zu sehen:

docker run --rm python:latest python --version

Dieser Befehl bewirkt Folgendes:

  1. docker run erstellt und startet einen neuen Container.
  2. --rm weist Docker an, den Container nach dem Beenden automatisch zu entfernen.
  3. python:latest gibt an, welches Image verwendet werden soll.
  4. python --version ist der Befehl, der im Inneren des Containers ausgeführt wird.

In der Ausgabe sollten Sie die aktuelle Python-Version sehen.

Wiederholen wir das Ganze mit Python 3.7:

docker run python:3.7 python --version

Diesmal sollten Sie Python 3.7.x in der Ausgabe sehen, wobei x für die letzte Patch-Version von Python 3.7 steht.

Diese Befehle demonstrieren, wie Sie verschiedene Versionen derselben Software nutzen können, indem Sie unterschiedliche Image-Tags verwenden. Dies ist extrem nützlich, wenn Sie Anwendungen ausführen müssen, die spezifische Python-Versionen (oder andere Softwareversionen) voraussetzen.

Images auflisten und entfernen

Während der Arbeit mit Docker werden sich mit der Zeit viele Images ansammeln. Es ist wichtig zu wissen, wie man diese verwaltet, also wie man sie auflistet und nicht mehr benötigte Images löscht.

Beginnen wir mit dem Auflisten aller Images auf Ihrem System:

docker images

Sie sollten eine Liste aller bisher abgerufenen Images sehen, einschließlich Nginx und der Python-Images.

Angenommen, wir möchten das Python 3.7 Image entfernen, um Speicherplatz freizugeben. Dies geschieht mit dem Befehl docker rmi (rmi steht für "remove image"):

docker rmi python:3.7

Wenn der Befehl erfolgreich ist, sehen Sie eine Ausgabe wie diese:

Untagged: python:3.7
Untagged: python@sha256:1f93c63...
Deleted: sha256:1f1a7b57...
Deleted: sha256:8c75ecde...
...

Es kann jedoch vorkommen, dass Sie stattdessen eine Fehlermeldung erhalten:

Error response from daemon: conflict: unable to remove repository reference "python:3.7" (must force) - container <container_id> is using its referenced image <image_id>

Dieser Fehler tritt auf, wenn noch ein Container (egal ob laufend oder gestoppt) existiert, der auf Basis dieses Images erstellt wurde. Docker verhindert das Löschen von Images, die noch in Gebrauch sind, um die Systemintegrität zu wahren.

Um dies zu beheben, müssen wir zuerst alle Container entfernen, die dieses Image nutzen. Listen wir alle Container auf (auch die gestoppten):

docker ps -a

Suchen Sie nach Containern, die aus dem Image python:3.7 erstellt wurden. Wenn Sie welche finden, entfernen Sie diese mit dem Befehl docker rm:

docker rm <container_id>

Ersetzen Sie <container_id> durch die tatsächliche ID des Containers, den Sie löschen möchten.

Versuchen Sie nun erneut, das Image zu entfernen:

docker rmi python:3.7

Diesmal sollte es funktionieren.

Überprüfen wir, ob das Image entfernt wurde, indem wir die Python-Images erneut auflisten:

docker images python

Das Image Python 3.7 sollte nicht mehr in der Liste erscheinen.

Image-Layer verstehen

Docker-Images basieren auf einem geschichteten Dateisystem (Layered Filesystem). Jeder Layer repräsentiert eine Reihe von Änderungen am Dateisystem. Dieser schichtweise Aufbau ermöglicht Docker eine hohe Effizienz bei der Speicherung und Netzwerknutzung. Lassen Sie uns dieses Konzept untersuchen.

Zuerst inspizieren wir die Layer des Nginx-Images, das wir zuvor abgerufen haben:

docker inspect --format='{{.RootFS.Layers}}' nginx

Sie sehen eine Ausgabe ähnlich dieser:

[sha256:2edcec3590a4ec7f40cf0743c15d78fb39d8326bc029073b41ef9727da6c851f sha256:e379e8aedd4d72bb4c529a4ca07a4e4d230b5a1d3f7a61bc80179e8f02421ad8 sha256:b5357ce95c68acd9c9672ec76e3b2a2ff3f8f62a2bcc1866b8811572f4d409af]

Jede dieser langen Zeichenfolgen (SHA256-Hashes) repräsentiert einen Layer im Image. Jeder Layer entspricht in der Regel einem Befehl im Dockerfile, mit dem das Image erstellt wurde.

Um Layer besser zu verstehen, erstellen wir ein einfaches eigenes Image. Erstellen Sie zunächst eine neue Datei namens Dockerfile in Ihrem aktuellen Verzeichnis:

nano Dockerfile

Fügen Sie in dieser Datei den folgenden Inhalt ein:

FROM nginx
RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html

Dieses Dockerfile macht zwei Dinge:

  1. Es basiert auf dem Nginx-Image, das wir zuvor abgerufen haben (FROM nginx).
  2. Es fügt dem Image eine neue Datei hinzu (RUN echo...).

Speichern und schließen Sie die Datei (in nano drücken Sie dazu Strg+X, dann Y und schließlich die Eingabetaste).

Nun bauen wir dieses Image:

docker build -t custom-nginx .

Beispielhafte Ausgabe:

Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM nginx
 ---> 5ef79149e0ec
Step 2/2 : RUN echo "Hello from custom layer" > /usr/share/nginx/html/hello.html
 ---> Running in 2fa43e649234
Removing intermediate container 2fa43e649234
 ---> 73b62663b5c3
Successfully built 73b62663b5c3
Successfully tagged custom-nginx:latest

Dieser Befehl erstellt ein neues Image basierend auf unserem Dockerfile und gibt ihm den Tag custom-nginx. Der Punkt . am Ende weist Docker an, das Dockerfile im aktuellen Verzeichnis zu suchen.

Inspizieren wir nun die Layer unseres benutzerdefinierten Images:

docker inspect --format='{{.RootFS.Layers}}' custom-nginx

Sie werden feststellen, dass dieses Image einen Layer mehr hat als das ursprüngliche Nginx-Image. Dieser zusätzliche Layer repräsentiert die Änderungen, die durch unseren RUN-Befehl vorgenommen wurden.

Das Verständnis von Layern ist aus folgenden Gründen entscheidend:

  1. Layer werden zwischengespeichert (Caching), was den Bau ähnlicher Images beschleunigt.
  2. Layer werden zwischen Images geteilt, was Festplattenplatz spart.
  3. Beim Hoch- oder Herunterladen von Images müssen nur die geänderten Layer übertragen werden.

Suche nach Images auf dem Docker Hub

Der Docker Hub beherbergt eine riesige Sammlung von Images. Während Sie Images auf der Docker Hub-Website suchen können, bietet Docker auch ein Kommandozeilen-Tool an, um direkt vom Terminal aus zu suchen.

Suchen wir zunächst nach Nginx-Images:

docker search nginx

Dies gibt eine Liste von Images zurück, die mit Nginx in Verbindung stehen. Die Ausgabe enthält mehrere Spalten:

  • NAME: Der Name des Images.
  • DESCRIPTION: Eine kurze Beschreibung des Images.
  • STARS: Die Anzahl der Sterne, die das Image auf Docker Hub hat (ein Indikator für Beliebtheit).
  • OFFICIAL: Gibt an, ob es sich um ein offizielles, von Docker gepflegtes Image handelt.
  • AUTOMATED: Gibt an, ob dieses Image automatisch aus einem GitHub-Repository erstellt wird.

Beispielhaft könnte das so aussehen:

NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                        15763     [OK]
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker c...   2088                 [OK]
...

Das offizielle Nginx-Image steht normalerweise ganz oben in dieser Liste.

Versuchen wir nun, nach einer spezifischen Python-Version zu suchen:

docker search python:3.8

Sie werden feststellen, dass diese Suche nicht ganz so funktioniert wie erwartet. docker search unterstützt keine Suche nach spezifischen Tags (wie 3.8). Stattdessen wird nach Images gesucht, die "python:3.8" im Namen oder in der Beschreibung enthalten.

Um spezifische Versionen eines Images zu finden, ist es oft besser:

  1. Nach dem allgemeinen Image-Namen zu suchen (z. B. docker search python).
  2. Die Docker Hub-Website für detaillierte Informationen zu besuchen.
  3. Das Image mit docker pull herunterzuladen und es dann lokal zu inspizieren.

Denken Sie daran: docker search ist ein schneller Weg, um Images zu finden, aber für detaillierte Informationen ist die Docker Hub-Website oft nützlicher.

Images speichern und laden

Docker ermöglicht es Ihnen, Images als tar-Dateien zu speichern und später wieder zu laden. Dies ist nützlich, um Images zwischen Systemen ohne Registry zu übertragen oder um Backups von Images zu erstellen.

Speichern wir zunächst das Nginx-Image in einer Datei:

docker save nginx > nginx.tar

Dieser Befehl speichert das Nginx-Image in einer Datei namens nginx.tar in Ihrem aktuellen Verzeichnis. Das Symbol > wird verwendet, um die Ausgabe des docker save-Befehls in eine Datei umzuleiten.

Sie können überprüfen, ob die Datei erstellt wurde, indem Sie den Inhalt Ihres aktuellen Verzeichnisses auflisten:

ls -lh nginx.tar

Sie sollten die Datei nginx.tar sehen, zusammen mit ihrer Größe (die über 100 MB liegen sollte).

Nun entfernen wir das Nginx-Image von unserem System, um die Übertragung auf ein System zu simulieren, das das Image noch nicht besitzt:

docker rmi nginx

Überprüfen Sie, ob das Image weg ist:

docker images nginx

Sie sollten keine Ergebnisse sehen, was bestätigt, dass das Nginx-Image von Ihrem System gelöscht wurde.

Laden wir nun das Image aus der tar-Datei wieder zurück:

docker load < nginx.tar

Das Symbol < wird verwendet, um den Inhalt der Datei nginx.tar als Eingabe für den Befehl docker load zu verwenden.

Nachdem der Ladevorgang abgeschlossen ist, überprüfen Sie, ob das Nginx-Image wieder da ist:

docker images nginx

Das Nginx-Image sollte wieder in der Liste erscheinen, genau wie vor dem Löschen.

Dieser Prozess des Speicherns und Ladens ist sehr nützlich, wenn Sie:

  • Images auf ein System ohne Internetzugang übertragen müssen.
  • Backups von spezifischen Image-Versionen erstellen wollen.
  • Eigene Images mit anderen teilen möchten, ohne eine Registry zu verwenden.

Grundlagen des Image-Taggings

Tagging ist eine Methode, um Aliase für Ihre Docker-Images zu erstellen. Es wird häufig für die Versionierung und Organisation von Images verwendet. Lassen Sie uns untersuchen, wie man Images taggt.

Zuerst erstellen wir einen neuen Tag für unser Nginx-Image:

docker tag nginx:latest my-nginx:v1

Dieser Befehl erstellt einen neuen Tag my-nginx:v1, der auf dasselbe Image wie nginx:latest verweist. Hier ist die Bedeutung der einzelnen Teile:

  • nginx:latest ist das Quell-Image und dessen Tag.
  • my-nginx ist der neue Image-Name, den wir vergeben.
  • v1 ist der neue Tag, den wir zuweisen.

Listen Sie nun Ihre Images auf, um den neuen Tag zu sehen:

docker images

Sie sollten sowohl nginx:latest als auch my-nginx:v1 in der Liste sehen. Beachten Sie, dass beide dieselbe Image ID haben – das liegt daran, dass es sich tatsächlich um dasselbe Image handelt, das lediglich unter verschiedenen Namen geführt wird.

Sie können diesen neuen Tag verwenden, um einen Container zu starten:

docker run -d --name my-nginx-container my-nginx:v1

Dieser Befehl bewirkt Folgendes:

  • -d führt den Container im Detached-Modus (im Hintergrund) aus.
  • --name my-nginx-container gibt unserem neuen Container einen Namen.
  • my-nginx:v1 ist das Image und der Tag, den wir zum Erstellen des Containers verwenden.

Überprüfen Sie, ob der Container läuft:

docker ps

Sie sollten Ihren Container in der Liste der laufenden Container sehen.

Tagging ist aus mehreren Gründen nützlich:

  1. Versionskontrolle: Sie können Images mit Versionsnummern versehen (v1, v2 usw.).
  2. Trennung von Umgebungen: Sie können Images für verschiedene Umgebungen taggen (dev, staging, prod).
  3. Lesbarkeit: Benutzerdefinierte Tags können verdeutlichen, wofür ein Image gedacht ist.

Denken Sie daran: Tags sind nur Aliase – sie erzeugen keine neuen Images, sondern lediglich neue Namen, die auf bestehende Images verweisen.

Zusammenfassung

In diesem Lab haben wir verschiedene Aspekte der Arbeit mit Docker-Images kennengelernt. Wir haben gelernt, wie man:

  1. Images aus dem Docker Hub abruft.
  2. Container mit verschiedenen Image-Versionen ausführt.
  3. Images auflistet und entfernt.
  4. Das Konzept der Image-Layer versteht.
  5. Auf dem Docker Hub nach Images sucht.
  6. Images speichert und lädt.
  7. Grundlegendes Image-Tagging durchführt.

Diese Fähigkeiten bilden die Grundlage für eine effektive Verwaltung von Docker-Images in Ihren Projekten. Auf Ihrem weiteren Weg mit Docker werden diese Operationen unerlässlich sein, um containerisierte Anwendungen zu erstellen und bereitzustellen.

Denken Sie daran: Docker-Images sind das Herzstück der Funktionsweise von Docker. Sie bieten eine konsistente, portable und effiziente Methode zum Paketieren und Verteilen von Anwendungen. Mit der Beherrschung dieser Image-Operationen sind Sie auf dem besten Weg, ein Docker-Experte zu werden.

Üben Sie diese Befehle weiter und experimentieren Sie mit verschiedenen Images. Je mehr Sie mit Docker arbeiten, desto sicherer und versierter werden Sie. Viel Spaß beim Dockern!