Docker/Buch/03 Grundlagen/Beschreibung
Beschreibung
Konzepte und Grundlagen von Docker
Grundlegende Fragen
- Was sind Images und Container?
- Wie unterscheiden sie sich voneinander?
- Wie können Netzwerkports eines Containers an den Host weitergeleitet werden?
- Wo werden veränderliche Daten eines Containers gespeichert?
- Wie kommunizieren Container miteinander?
- Beispiele
Praktische Beispiele
- Einen Ubuntu-Container interaktiv bedienen
- Docker-Container im Hintergrund starten
- Im Webbrowser Ihres Computers nutzen
- Datenbankserver so betreiben, dass andere Container (z. B. mit WordPress) darauf zugreifen können
- Kommando docker/Befehl
- Administration von Docker-Images und -Containern
- Referenz der Docker/Befehle
- Podman
Falls Sie Podman installiert haben, kommt anstelle von docker das (fast) gleichwertige Kommando podman zum Einsatz
- Wo es Unterschiede in der Anwendung gibt, weisen wir darauf hin
Grundlagen und Nomenklatur
Wichtige Begriffe
- aus der Container-Welt
- Überblick wie Docker funktioniert
- Interna zur technischen Realisierung
siehe Tipps, Tricks und Interna
- Images und Container
Der Ausgangspunkt für die Ausführung jedes Containers ist ein Image.
- Den Begriff kennen Sie vielleicht schon von virtuellen Maschinen: Dort ist ein Disk-Image eine Datei, die dem Virtualisierungssystem als Datenträger (Festplatte oder SSD) präsentiert wird.
- Die virtuelle Maschine kann dort Partitionen und Dateisysteme einrichten.
Bei Docker und Podman stellt ein Image hingegen als Read-only-Dateisystem die Basis für den Container zur Verfügung.
- Anders als bei virtuellen Maschinen wird das Image durch den laufenden Container nie verändert.
- Alle vom Container veränderten oder hinzugefügten Dateien landen stattdessen in einem getrennten Overlay- Dateisystem, wobei dieses auf dem Host durch ein eigenes Verzeichnis innerhalb des Docker-Basisverzeichnisses abgebildet wird.
Die Trennung zwischen unveränderlichen Image-Dateien und veränderlichen Container-Dateien macht es möglich, von einem Image beliebig viele Container abzuleiten, die durchaus auch zugleich ausgeführt werden können. Im Internet und speziell im Docker Hub steht eine Menge Images zum Download zur Auswahl, die überwiegende Anzahl davon ist kostenlos.
- Aus diesen Images können Sie sich wie aus einem Werkzeugkasten bedienen: Sie können von ihnen eigene Container ableiten und diese sogar selbst zu neuen Images kombinieren.
In Teil II dieses Buchs, »Werkzeugkasten«, geben wir Ihnen einen Überblick über die wichtigsten Standard-Images für Programmiersprachen, Datenbank- und Webserver sowie für komplette Webapplikationen.
- Der Docker Hub
Der Docker Hub wird zwar von der Firma Docker betrieben, die dort angebotenen Images stammen aber überwiegend von der Docker-Community.
- Nach dem Einrichten eines Logins kann hier jeder kostenlos Images öffentlich anbieten.
- Das ist natürlich ein fantastisches Angebot.
- Es hat aber zur Folge, dass auf dem Docker Hub neben vielen tollen Images auch eine Menge Schrott zu finden ist – Testprojekte, nicht mehr gewartete Software und dergleichen.
- Insofern sollten Sie bei der Auswahl von Images
auf dem Docker Hub ein wenig Vorsicht walten lassen.
- Uneingeschränkt empfeh-
lenswert sind in der Regel »offizielle« Images, die von der Firma Docker gewartet werden: https://hub.docker.com Neben dem Docker Hub gibt es diverse weitere Registries von anderen Firmen, unter anderem von Red Hat und GitHub.
- Während Docker standardmäßig nur im Docker Hub nach Images sucht, sind bei Podman in der Regel mehrere Registries vorkonfiguriert; bei Bedarf können weitere hinzugefügt werden (siehe Abschnitt 6.8,
»Podman-Interna«).
- Volumes
Eine Grundidee von Docker besteht darin, dass bei einem Update der Images (z. B. wegen einer neuen Softwareversion) einfach der laufende Container gestoppt und ein
neuer Container eingerichtet wird, der den alten ersetzt. (Weder das Update noch der Container-Neustart erfolgt automatisch.
- Sie müssen sich selbst darum kümmern.)
Soweit es den im Image enthaltenen Programmcode betrifft, ist dieses Konzept ebenso simpel wie genial – aber was ist mit den Dateien, die während des Betriebs des Containers entstanden sind? Es ist ja nicht akzeptabel, dass sie beim Einrichten eines neuen Containers alle verloren gehen. Um das zu vermeiden, sieht Docker Volumes vor: Volumes sind vom Container getrennte Verzeichnisse im Host-Dateisystem.
- Dort werden diejenigen Dateien gespeichert, die beim Wechsel von einer Version zur nächsten, also von einem Container zum nächsten, erhalten bleiben sollen.
- Bei einem Container mit einem Datenbankserver befinden sich in einem derartigen Volume z. B. alle Datenbankdateien, bei einem Container mit einem Webserver die HTML-Dokumente, PHP-Scripts etc.
Standardmäßig richten Docker und Podman beim Erstellen von Containern, die Volumes benötigen, automatisch ein dazugehörendes Verzeichnis ein (unter Linux im Verzeichnis /var/lib/docker/volumes , .local/share/docker/volumes oder in .local/share/containers/storage/volumes ) und benennt es mit einer UUID.
- Zur besseren Administration können Sie Volumes einen eigenen Namen geben oder sogar den Ort des Verzeichnisses vorgeben.
- Sie vermeiden damit lange Pfadnamen, die unmöglich zu merken sind.
- Wenn Sie nicht wissen, wo sich das Volume eines Containers befindet, können Sie diese Information mit docker inspect ermitteln.
- Services, Stacks und Cluster
Solange Sie Docker auf einem Rechner ausführen, ist das Konzept der Container ausreichend.
- Sobald es aber darum geht, Dienste über mehrere Rechner (über mehrere Docker-Hosts) zu verteilen, steigt der administrative Aufwand erheblich.
- Um Docker in solchen Fällen besser skalierbar zu machen sowie um Load-Balancingund High- Availability-Funktionen zu realisieren, wurde das Konzept der Services eingeführt.
Ein Service beschreibt einen Dienst bzw. eine Aufgabe. Ähnlich wie bei einem Container geben Sie bei der Definition eines Service an, auf welches Image Sie sich beziehen und welches Kommando letztlich ausgeführt werden soll.
- Der wesentliche Unterschied zu Containern besteht darin, dass Sie sich um die Ausführung von Services nicht selbst kümmern, sondern dass Docker diese Aufgabe übernimmt.
- Insbesondere entscheidet Docker anhand von Regeln, auf welchen Docker-Hosts der Service ausgeführt wird. (Hinter den Kulissen wird zur Ausführung eines Service natürlich ein Container eingerichtet und gestartet.
- Services ersetzen Container also nicht, sondern bilden eine zusätzliche Verwaltungsebene.)
In der Docker-Praxis werden oft mehrere Services kombiniert.
- Erst das aus dieser Kombination entstehende Gesamtprodukt kann sinnvoll getestet bzw. genutzt werden.
- Mit Stacks wird die Administration solcher Servicegruppen vereinfacht.
- Das entsprechende Kommando docker stack kann mehrere zusammengehörende Services gemeinsam einrichten, starten oder stoppen.
Die Grundvoraussetzung für die Verwendung von Services und Stacks besteht darin, dass Sie vorher einen Cluster aus Docker-Hosts zusammensetzen.
- In der Docker- Nomenklatur spricht man aber nicht von einem Cluster, sondern von einem Schwarm bzw. im Englischen von einem Swarm.
- Ein Schwarm besteht aus mehreren Docker- Instanzen, die durch eine relativ simple Konfiguration mit docker swarm init und docker swarm join verbunden werden.
- Im Extremfall kann ein Schwarm sogar aus nur einer einzigen Docker-Instanz bestehen.
- Das reicht für erste Tests aus; die Vorteile eines Cluster-Systems können sich dabei aber natürlich nicht manifestieren.
Erste Beispiele zur Anwendung von Services und Stacks finden Sie in Kapitel 5, »Container-Setups mit compose«.
- Dort geht es um compose.yaml-Dateien, die eine ganze Gruppe von Containern bzw. Services beschreiben.
- Umfangreichere Beispiele zur Anwendung von Docker-Clustern folgen in Teil III des Buchs und insbesondere in Kapitel 19, »Swarm«.
Eine Alternative zu Docker Swarm ist Kubernetes.
- Dabei handelt es sich um ein von Google entwickeltes Open-Source-Programm zur Verwaltung von Containern.
- Kubernetes unterstützt auch andere Container-Systeme, wird aber oft in Kombination mit Docker eingesetzt.
- Kubernetes hat mittlerweile eine wesentlich höhere Verbreitung als Docker Swarm erzielt.
- Details zu Kubernetes finden Sie in Kapitel 20, »Kubernetes«.
- docker-Kommando versus Docker-Dämon (dockerd)
Docker ist als Client-Server-Modell realisiert.
- Für die Ausführung der Container ist der im Hintergrund laufende Docker-Dämon zuständig.
- Für dieses Programm ist auch die Bezeichnung Docker Engine üblich.
- Unter Linux handelt es sich dabei um den Prozess dockerd .
- Unter macOS bzw. Windows sind die Funktionen dagegen über mehrere Prozesse verteilt, deren Namen mit com.docker oder Docker beginnen.
- Insbesondere muss unter macOS bzw. unter Windows zusätzlich eine virtuelle Maschine mit einer winzigen Linux-Distribution ausgeführt werden, um die für Docker erforderlichen Funktionen zur Verfügung zu stellen.
Zur Steuerung des Dämons bzw. der Docker Engine verwenden Sie das Kommando docker.
- Häufig laufen der Docker-Dämon und docker auf demselben Host.
- Es ist aber auch möglich, mit docker eine Netzwerkverbindung zu einem externen Docker- Dämon herzustellen.
Podman verhält sich diesbezüglich komplett anders als Docker: Es gibt normalerweise keinen Hintergrundprozess.
- Vielmehr werden alle Container direkt durch das
podman-Kommando gestartet bzw. wieder beendet.
- Mehr Informationen zu diesem Podman-spezifischen Detail folgen in Abschnitt 6.8, »Podman-Interna«.
- Linux versus Windows
Im Produktivbetrieb wird Docker am häufigsten dazu eingesetzt, Programme aus der Linux-Welt auf einem Linux-Server (Docker-Host) auszuführen.
- Bevor ein Programm produktiv läuft, muss es aber entwickelt werden – und das können Sie mit wenigen Einschränkungen ebenso gut unter macOS oder unter Windows tun.
Mit anderen Worten: Sie können Ihre neue Webapplikation wahlweise unter einer Linux-Desktop-Distribution, unter macOS oder unter Windows entwickeln.
- Wenn alles zufriedenstellend läuft, nehmen Sie den Docker-Container auf einem Linux- Server oder in einer Cloud in Betrieb.
- Tipps zur Umstellung vom Test- auf den Live-Betrieb, also zum sogenannten Deployment, finden Sie in Kapitel 17, »Continuous Integration und Continuous Delivery«.
Während Docker als Tool für Linux-affine Entwickler schon seit Jahren etabliert ist, wächst gleichzeitig das Angebot von Docker-Images, die speziell für Windows gedacht sind.
- Dazu zählen z. B. eine Minimalversion von Windows Server (der sogenannte Nano Server), der Internet Information Server (IIS) oder ASP.NET.
- Derartige Images können allerdings nur mit der Docker-Version für Windows ausgeführt werden.
- Zum Teil wird aus Lizenzgründen auch die Betriebssystem-Variante des Hosts überprüft.
So können Sie den Nano Server nicht unter Windows Home oder Pro ausprobieren; vielmehr benötigen Sie eine Windows-Server-Instanz. Aus der Sicht von Microsoft ist das verständlich: Die Firma verdient ihr Geld ja unter anderem mit dem Verkauf von Serverlizenzen.
- Da wäre es kontraproduktiv, das Ausführen eines Windows-Server-Containers auf einem Rechner zu erlauben, der nicht selbst ein Windows-Server ist.
- Andererseits sind es genau solche Einschränkungen, die das Leben für Entwickler mühsam machen und diese beinahe schon mit Gewalt in das Linux-Segment drängen.
Linux-Host Windows-Host macOS-Host Container auf Linux-Basis O.
- K. O.
- K. O.
- K.
Container auf Windows-Basis — O.
- K. —
Tabelle 3.1 Container auf Linux-Basis laufen auf allen Docker-Hosts, solche auf Windows- Basis allerdings nur auf Windows-Docker-Hosts.
In diesem Buch behandeln wir Docker, soweit es den Host betrifft, plattformübergreifend.
- Bei den Containern konzentrieren wir uns hingegen auf Open-Source-Software, die zumeist aus der Linux-Welt stammt.
Docker Engine zwischen Linux- und Windows-Containern umschalten Ein unter Windows laufender Docker-Host kann sowohl Linux- als auch Windows- Container ausführen (siehe Tabelle 3.1) – aber nicht gleichzeitig! Standardmäßig ist auch die Windows-Version von Docker dafür konfiguriert, Linux-Container auszu- führen. Wenn Sie stattdessen Windows-Container nutzen möchten, müssen Sie im Docker- Menü (das Sie über das Icon im Infobereich der Taskleiste erreichen) Switch to Windows containers ausführen.
Nach dem obligatorischen Windows-Neustart können Sie nun Windows-Container ausführen.
- Ein Wechsel zurück in die Linux-Welt gelingt analog mit Switch to Linux containers, und das erstaunlicherweise ohne einen weiteren Windows-Neustart.
- Der Wechsel zwischen den beiden Welten erfolgt ohne Datenverlust: Bereits heruntergeladene Images, eingerichtete Container etc. bleiben also erhalten.
- Podman ist nicht in der Lage, Windows-Container auszuführen.
Virtuelle Maschinen versus Container Auch wenn virtuelle Maschinen und Container ähnliche Ziele verfolgen, z. B. diverse Testprogramme oder Serveranwendungen auf einem physischen Rechner möglichst isoliert voneinander auszuführen, so unterscheidet sich die Funktionsweise doch fundamental. Bei jeder virtuellen Maschine wird die gesamte Hardware eines PCs durch Software nachgebildet.
- Die virtuelle Maschine hat den Eindruck, auf einem echten Rechner zu laufen.
- Das erfordert aber einen riesigen Ressourcenaufwand (RAM, Speicherplatz auf dem Datenträger, CPU-Zyklen).
Container nutzen dagegen direkt die Infrastruktur des Host-Systems, also insbesondere sein Dateisystem und einen gemeinsamen Kernel.
- Bei einer »gewöhnlichen«
Docker-Installation unter Linux handelt es sich dabei einfach um den Kernel des Host- Rechners.
- Die Container laufen gewissermaßen wie isolierte Prozesse (ähnlich wie Sandboxes) direkt im Host-System.
Wird Docker dagegen unter macOS, Windows oder in Kombination mit Docker Desktop für Linux ausgeführt, läuft getrennt vom eigentlichen Betriebssystem ein für Docker optimierter Linux-Kernel.
- Analog gilt dies auch für Podman unter Windows und macOS.
Der Platzbedarf von Containern ist in der Regel viel geringer als der von virtuellen Maschinen, weil der Unterbau auf ein Minimum reduziert werden kann.
- Zudem starten Container deutlich schneller.
Der Vorteil von virtuellen Maschinen besteht darin, dass sie besser und sicherer voneinander getrennt sind als Container.
- Die Verwendung eines gemeinsamen Kernels macht eine vollständige Isolierung schwierig.
Für Container spricht andererseits der stark reduzierte Overhead.
- Zudem lassen sich Container sekundenschnell script-gesteuert erzeugen und konfigurieren.
- Wenn es darum geht, Anwendungen automatisiert einzurichten, sei es für Testzwecke oder zur Skalierung, bieten Docker und Podman riesige Vorteile gegenüber den vergleichsweise schwerfälligen virtuellen Maschinen.
- Während es bei virtuellen Maschinen meist zweckmäßig ist, mehrere zusammengehörige Dienste in einer virtuellen Maschine zusammenzufassen, kann bei Docker jede Funktion ihren eigenen Container bekommen.
- In diesem Zusammenhang spricht man oft von der Micro Services Architecture.
Virtualisierung und Container schließen sich keineswegs aus.
- In der Praxis kommt es beispielsweise oft vor, dass die Docker Engine selbst wieder in einer virtuellen Maschine läuft.
Container ausführen
Um sich mit Docker und Podman und seiner Nomenklatur vertraut zu machen, empfehlen wir Ihnen, einige Stunden zu experimentieren (also »herumzuspielen«, wenn Sie so wollen).
- Die folgenden Abschnitte geben Ihnen dazu Anregungen.
Wir weisen explizit darauf hin, dass das Ziel dieser Beispiele nicht der Start eines echten Entwicklungssystems oder gar der produktive Einsatz ist.
- Konkrete Anleitungen zur Verwendung wichtiger Images folgen in Teil II, »Werkzeugkasten«.
- An dieser Stelle geht es vielmehr darum, die Konzepte von Docker und Podman anhand von Beispielen kennen zu lernen – Learning by Doing also.
Für allererste Tests, die in ihrer Funktionalität noch simpler sind als unser Hello- World-Beispiel aus Kapitel 1, gibt es im Docker Hub (https://hub.docker.com) sowie in einigen anderen Registries ein spezielles Hello-World-Image.
- Um dieses Image auszuprobieren und den davon abgeleiteten Container zu starten, führen Sie in einem Terminal eines der drei folgenden Kommandos aus:
docker run hello - world ( f ü r Docker unter macOS und Windows , Rootless Docker , Docker Desktop f ür Linux )
sudo docker run hello - world ( Docker Engine unter Linux )
podman run hello - world ( Podman )
Das jeweilige Kommando sieht zuerst nach, ob das Image hello-world auf dem lokalen Rechner bereits zur Verfügung steht.
- Ist das nicht der Fall, wird es vom Docker Hub heruntergeladen und lokal gespeichert.
- Docker bzw. Podman bildet daraus einen Container und führt diesen schließlich aus:
docker run hello - world Unable to find image 'hello - world : latest ' locally latest : Pulling from library /hello -world b8dfde12 7 a 2 9 : Pull complete Digest : sha256 : f226 ...
- d519
Status : Download ed newer image for hello -world :latest
Hello from Docker ! This message shows that your installa t i o n appears to be working correctl y . ...
Ab dem zweiten Mal wird docker run hello-world blitzschnell ausgeführt, weil jetzt ein lokaler Container der Hello-World-App zur Verfügung steht. Das offizielle Hello-World-Image ist insofern ein untypisches Docker-Beispiel, als die darin verpackte App einmal ausgeführt wird und dann sofort endet.
- Viele Docker- Container enthalten dagegen Programme, die Eingaben verarbeiten, dauerhaft laufen oder interaktiv genutzt werden können.
- Ständig »sudo«?
Die in diesem Kapitel präsentierten Beispiele können Sie grundsätzlich unter jedem Betriebssystem ausprobieren.
- Aber während Sie das Kommando docker unter macOS
oder Windows in einem gewöhnlichen Benutzeraccount ausführen können, benötigt es unter Linux root-Rechte (es sei denn, Sie verwenden Rootless Docker oder Docker Desktop für Linux – siehe Abschnitt 2.5 und Abschnitt 2.6). Da es lästig ist, ständig mit root-Rechten zu arbeiten oder jedem docker-Kommando sudo voranzustellen, gibt es einen Ausweg: Sie fügen Ihren Linux-Account der Gruppe docker hinzu: usermod -aG docker <accountname> Damit diese Änderung wirksam wird, müssen Sie sich ab- und wieder anmelden. Danach können Sie das Kommando docker auch unter Linux ohne Weiteres ausfüh- ren.
- Beachten Sie, dass die scheinbar harmlose Gruppenzuordnung dem betreffenden
Benutzer indirekt root-Rechte gibt (siehe Abschnitt 6.7, »Docker-Interna«).
- Statusinformationen
docker ps -a liefert eine Liste aller laufenden bzw. in der Vergangenheit ausgeführten Docker-Container.
- Die merkwürdigen Namen in der Spalte NAMES resultieren daraus, dass Docker jedem Container nicht nur eine zufällige ID zuweist, sondern auch einen leichter zu merkenden (aber ebenso zufälligen) Namen.
docker ps -a CONTAINE R ID IMAGE COMMAND ... NAMES f5269c75 9 b 7 d hello - world "/ hello " nervous_l a m a r r c6770e95 f d d 3 hello - world "/ hello " kind_wrig h t
docker images listet die lokal installierten Images auf:
docker images REPOSITO R Y TAG IMAGE ID CREATED SIZE hello -world latest 48 b5124b27 6 8 7 weeks ago 1.84 kB
- Das richtige Kommando
Auch den obigen Kommandos müssen Sie gegebenenfalls sudo voranstellen.
- Falls Sie mit Podman arbeiten, ersetzen Sie docker durch podman.
- In Zukunft geben wir immer nur das Kommando docker an, ohne auf diese Differenzierung hinzuweisen.
- Aufräumen
Es besteht die Gefahr, dass sich rasch unzählige Container ansammeln, die einmal ausgeführt wurden, aber nicht mehr benötigt werden.
- Deswegen sollten Sie nicht mehr benötigte Container gleich wieder löschen:
docker rm nervous_ la m a r r kind_wri g h t
Wenn Sie erwarten, dass Sie das zugrundeliegende Image auch nicht mehr benötigen (in diesem Fall, weil Sie nicht vorhaben, run hello-world noch öfter auszuführen), dann können Sie auch das Image löschen.
- Sollten Sie hello-world später doch noch einmal brauchen, wird das Image eben neuerlich heruntergeladen.
docker image rm hello - world
Container einmal starten und sofort wieder löschen
Wenn Sie von vornherein wissen, dass Sie einen Container nur einmal ausführen und dann unmittelbar wieder löschen möchten, können Sie die zusätzliche Option --rm (mit zwei vorangestellten Bindestrichen) übergeben: docker run --rm hello-world
Container interaktiv verwenden
Während der hello-world-Container einmal ausgeführt nach der Ausgabe einiger Textzeilen gleich wieder endet, können viele andere Container interaktiv genutzt werden.
- Gut geeignet für erste Experimente sind die offiziellen Base-Images von gängigen Linux-Distributionen, z. B. von Alpine, CentOS, Debian, Fedora, openSUSE, Oracle Linux oder Ubuntu.
Die Bezeichnung Base-Image rührt daher, dass diese Images als Startpunkt für eigene Entwicklungen gedacht sind.
- Wenn Sie also z. B. einen Container für einen Webserver zusammensetzen möchten, beginnen Sie mit dem Base-Image Ihrer Wunschdistribution und installieren darin Apache.
- Aus Docker-Sicht ist dann nicht ein vollkommen neues Image erforderlich, sondern das Base-Image kann um ein (vergleichsweise kleines) Image mit Ihren Erweiterungen ergänzt werden.
Für die folgenden Beispiele verwenden wir das Ubuntu-Image als Ausgangspunkt. Dabei spielt es keine Rolle, welche Distribution Sie für den Docker-Host verwenden. Sie können also Container des Ubuntu-Images auch unter Debian, Fedora, ja sogar unter macOS oder Windows ausführen! Vom Ubuntu-Image gibt es mehrere Versionen.
- Wenn Sie einfach docker run -it ubuntu ausführen, bekommen Sie die Version, die Docker mit dem Attribut latest ausgestattet hat.
- In der Regel ist das die gerade aktuelle LTS-Version.
- Wenn Sie davon abweichend eine andere Version wünschen, müssen Sie sie explizit angeben, also z. B. docker run -it ubuntu:23.04.
Informationen zur Konfiguration dieses Docker-Images können Sie hier nachlesen:
Die Optionen -i und -t beschreiben die Funktion des run-Kommandos weiter:
-i bedeutet, dass der Container interaktiv ausgeführt und mit der Standardeingabe verbunden werden soll. Wegen -t verwendet Docker einen Pseudo-Terminal-Emulator (Pseudo-TTY) und verbindet ihn mit der Standardeingabe.
Die Kombination dieser beiden Optionen ist erforderlich, wenn ein Container in einem Terminal- oder PowerShell-Fenster interaktiv bedient werden soll.
- In der Regel wird -i und -t zu -it abgekürzt.
Mit dem folgenden Kommando wird also das gerade aktuelle Ubuntu-LTS-Image heruntergeladen, ein darauf aufbauender Container erzeugt und schließlich ausgeführt. Sie landen dabei automatisch in einer Instanz der unter Ubuntu üblichen Shell bash, in der Sie nun Kommandos mit root-Rechten ausführen können:
docker run -it ubuntu
root@f8f e c 4 64 0 1 7 6 :/# cat / etc / os - release NAME =" Ubuntu " VERSION ="22.04.2 LTS ( Jammy Jellyfis h ) " ...
root@f8f e c 4 64 0 1 7 6 :/# df -h -x tmpfs Filesyst e m Size Used Avail Use % Mounted on overlay 20 G 11 G 7.6 G 59% /
root@f8f e c 4 64 0 1 7 6 :/# ps ax PID TTY STAT TIME COMMAND 1 ? Ss 0:00 / bin / bash 11 ? R+ 0:00 ps ax
root@f8f e c 4 64 0 1 7 6 :/# exit
- Kurz einige Erläuterungen
f8fec4640176 ist ein zufällig generierter Host-Name, den Docker dem Container zugewiesen hat. cat /etc/os-release gibt Informationen über die Distribution aus, die als Basis für den Container dient. df -h listet auf, wie viel Platz in den Dateisystemen des Containers frei ist.
- Die Ergebnisse hängen vom Docker-Host ab.
- Unter Linux wird das gesamte Dateisystem, in dem sich das Verzeichnis /var/lib/docker befindet, mit den Docker- Containern geteilt.
- Unter macOS und Windows ist für alle Container zusammen ein limitierter Speicher vorgesehen, in der Regel ca. 60 GByte. -x tmpfs eliminiert aus den df-Ausgaben alle temporären Dateisysteme, die nicht von Interesse sind.
ps ax liefert eine Liste aller laufenden Prozesse.
- Beachten Sie, dass im Container –
ganz im Gegensatz zu einer gewöhnlichen virtuellen Maschine – keinerlei andere Prozesse laufen: kein SSH-Server, kein Cron-Dämon, kein systemd-Dämon, kein Logging-Dienst, nichts! exit beendet die Ausführung des Containers.
- Alle weiteren Kommandos gelten dann wieder im Kontext des Terminals bzw. der PowerShell.
- Image-Namen Image-Namen von Containern setzen sich aus bis zu vier Teilen zusammen
registry/quelle/imagename:tag
registry gibt an, in welcher Registry das Image gespeichert ist.
- Die Angabe entfällt häufig.
- docker greift dann automatisch auf den Docker Hub zurück.
- podman stellt dagegen alle vorkonfigurierten Registries zur Wahl (siehe auch Abschnitt 6.8,
»Podman-Interna«).
- Bei podman run oder podman pull müssen Sie häufig mit docker.io den Docker Hub auswählen, weil viele wichtige Images nur dort verfügbar sind.
quelle ist der Name der Organisation, die das Image zusammengestellt und in den Docker Hub bzw. in eine andere Image-Registry hochgeladen hat.
- Entfällt die Angabe der Quelle, nimmt das docker-Kommando an, dass Sie eines der offiziellen Images der Firma Docker meinen.
imagename gibt erwartungsgemäß den Namen des Images an. Sofern es von dem Image mehrere Versionen gibt, wählt die optionale Angabe von tag explizit das mit diesem Tag gekennzeichnete Image aus.
- Entfällt die Versionsangabe, entscheidet sich docker für das mit latest gekennzeichnete Image.
Wenn Sie das Kommando docker run -it ubuntu nach ein paar Monaten wiederholen, kommt weiterhin das beim ersten Versuch heruntergeladene Ubuntu-Image zum Einsatz – selbst dann, wenn es längst eine neue Version gibt.
- Den Download einer aktuelleren Image-Version müssen Sie bei Bedarf mit dem Subkommando image pull selbst anstoßen:
docker image pull ubuntu Using default tag : latest latest : Pulling from library /ubuntu ...
Ubuntu versus Alpine Linux versus andere Distributionen Ubuntu zählt im Desktopund Serverbereich zu den populärsten Linux-Distributionen.
- Das macht Ubuntu aber nicht zum idealen Startpunkt für Docker! Der Hauptnachteil von Ubuntu besteht darin, dass es sich sogar in der Minimalform um eine relativ umfangreiche Distribution handelt.
- Unter Docker sind schlanke Distributionen vorzuziehen.
- Besonders beliebt ist in der Docker-Welt deswegen Alpine Linux, etwa als Basis für Images mit einem Webserver oder einer Programmiersprache.
- Eine Einführung in Alpine Linux geben wir in Kapitel 8.
Netzwerkanbindung
Mit hostname -I können Sie die IP-Adresse des Containers ermitteln.
- Docker und Podman verwenden standardmäßig unterschiedliche lokale Netze:
root@f8fe c 4 6 4 01 7 6 :/# hostname -I 172.17.0 . 2 ( Docker ) 10.0.2.1 0 0 fd00 ::84 bc :94 ff : feed :97 c8 ( Podman )
Die vertrauten Kommandos ip addr und ping funktionieren innerhalb des Ubuntu- Containers nicht, weil sie aus Platzgründen nicht im Image enthalten sind.
- Das lässt sich aber sehr schnell ändern:
root@f8fe c 4 6 4 01 7 6 :/# apt update && apt install -y \ iproute2 iputils - ping
root@f8fe c 4 6 4 01 7 6 :/# ip addr 1: lo : ... inet 127.0.0.1 / 8 scope host lo 41: eth0@if42 : ... inet 172.17.0. 2 / 1 6 scope global eth0
ip addr zeigt, dass die Netzwerkanbindung in ein privates Netzwerk führt, das Docker standardmäßig zur Verfügung stellt.
- Docker weist den Containern beim Start eindeutige IP-Adressen in diesem Netzwerk zu.
- Anders als bei virtuellen Maschinen kommt dabei allerdings nicht DHCP zum Einsatz.
ping beweist, dass die Container auch auf das Internet zugreifen können (andernfalls hätte vorhin auch apt update nicht funktioniert).
ping -c 1 google .
- de
PING google .de (142.250. 1 8 6 . 35 ) 56(84) bytes of data . 64 bytes from fra24s04 -in - f3 .1 e100 .net (142.250. 1 8 6 . 35 ) : ... 1 packets transmitted , 1 received , 0% packet loss , time 0 ms rtt min / avg /max / mdev = 19.221/1 9 . 2 21 / 1 9 . 22 1 / 0 . 00 0 ms
ping-Problem
Wir haben in Kapitel 2, »Installation«, schon darauf hingewiesen: Wenn Sie Rootless Docker verwenden, funktioniert ping bei manchen Host-Distributionen nicht.
- Um zu testen, ob eine Internetverbindung zu einem bekannten Webserver möglich ist, können Sie stattdessen wget <hostname> oder curl <hostname> verwenden.
- Damit laden Sie die Startseite der jeweiligen Website herunter (oft index.html).
Nochmals Container versus Images
Jetzt ist es an der Zeit, ein wenig mit dem Kommando docker bzw. podman zu experimentieren, damit Sie den Unterschied zwischen einem Image und seinen Containern verstehen lernen.
- Wenn Sie den Ubuntu-Container mit (Strg)+(D) oder exit verlassen und dann mit docker run neuerlich starten, wird Ihnen vielleicht auffallen, dass der Container einen neuen Host-Namen erhalten hat.
- Merkwürdig!
Versuchen Sie nun, mit touch eine neue Datei anzulegen.
- Beenden Sie den Container, führen Sie erneut docker run aus, und suchen Sie nach der Datei.
- Sie werden sie nicht finden.
- Können Docker bzw. Podman Veränderungen am Dateisystem denn nicht konsistent speichern?
docker run -it ubuntu root@168 a 2 e c6 4 8 f 0 :/# touch abc root@168 a 2 e c6 4 8 f 0 :/# exit
docker run -it ubuntu root@26a 4 a 5 f5 b 2 8 1 :/# ls -l abc ls : cannot access 'abc ': No such file or director y
Ein wenig klarer wird die Sache, wenn Sie ausprobieren, docker run in mehreren Terminalfenstern parallel auszuführen.
- Das ist kein Problem für Docker! Der Grund für dieses auf den ersten Blick merkwürdige Verhalten besteht darin, dass Docker jedes Mal, wenn Sie docker run imagename ausführen, einen neuen Container für dieses Image erzeugt!
Jeder Container erhält automatisch eine zufällige UID, deren Kurzform sich im Host- Namen widerspiegelt, sowie ein eigenes Dateisystem. (Genau genommen wird über das Read-only-Dateisystem des Images ein Read-Write-Dateisystem des Containers gelegt – siehe Abschnitt 6.7, »Docker-Interna«.)
docker ps -a | grep ubuntu CONTAINE R ID IMAGE STATUS NAMES 26 a4a5f5b2 8 1 ubuntu Exited (2) 6 seconds ago wizardly _ ... 168 a2ec648f 0 ubuntu Exited (0) 6 minutes ago musing_k i lb y f8fec464 0 1 7 6 ubuntu Up 36 minutes naughty_ b or g
Container mit »docker start« erneut ausführen
Um einen vorhandenen Container später weiterzuverwenden, müssen Sie ab dem zweiten Start explizit angeben, welchen Container Sie meinen.
- Dabei können Sie wahlweise die zufällige Container-ID oder den ebenso zufälligen, aber leichter zu merkenden Container-Namen verwenden (siehe das Ergebnis von docker ps -a).
Beachten Sie, dass Sie zum neuerlichen Start eines bereits vorhandenen Containers docker start verwenden müssen, nicht docker run! Damit Sie den Container interaktiv verwenden können, müssen Sie wieder die Option -i angeben. -t ist hingegen nicht zulässig. (Die meisten Optionen, die Sie beim Erzeugen eines Containers mit docker run angeben, werden dauerhaft im Container gespeichert. -i zählt zu den Ausnahmen.)
Dafür benötigen Sie bei Podman zusätzlich die Option -a, was zusammen mit -i zu -ai abgekürzt werden kann.
- Die Option -a bewirkt, dass die Standardeingabe und
-ausgabe des Containers mit der des Terminals verbunden wird.
- Bei Docker ist dies
bei docker -i start automatisch der Fall; die zusätzliche Option -a stört aber nicht.
Die folgenden zwei Beispiele zeigen, dass Docker die Datei abc durchaus gespeichert hat.
- Entscheidend ist nur, dass Sie beim nächsten Start die richtige Container-ID bzw.
den Container-Namen angeben.
docker start -ai musing_ki l b y root@168 a 2 e c6 4 8 f 0 :/# ls -l abc -rw -r - -r - -. 1 root root 0 Mar 10 15:27 abc root@168 a 2 e c6 4 8 f 0 :/# exit
docker start -ai 168 a2ec648f 0 root@168 a 2 e c6 4 8 f 0 :/# ls -l abc -rw -r - -r - -. 1 root root 0 Mar 10 15:27 abc root@168 a 2 e c6 4 8 f 0 :/# exit
Autovervollständigung
Bei der Eingabe von docker start können Sie die Container-ID bzw. den Namen des Containers unter Umständen mit (ê) vervollständigen.
- Diese Funktion steht allerdings nur unter Linux und macOS zur Verfügung.
Wenn Sie die zsh mit der Erweiterung Oh-My-Zsh verwenden, müssen Sie in .zshrc die plugins-Zeile um die Plugins docker und docker-compose erweitern.
- Weitere Konfigurationstipps speziell für macOS finden Sie hier:
https://docs.docker.com/desktop/faqs/macfaqs
Eigene Container-Namen
Die zufälligen Container-Namen sind zwar handlicher als die IDs, noch besser ist es aber, Containern eigene Namen zuzuordnen.
- Dazu geben Sie, wenn Sie den Container mit dem Kommando docker run erzeugen, mit --name den gewünschten Namen an.
Optional können Sie dem Container bei dieser Gelegenheit auch gleich mit -h einen Host-Namen zuweisen.
- Dieser kann, muss aber nicht mit dem Container-Namen übereinstimmen.
docker run -it --name myubuntu -h myubuntu ubuntu root@myu b u n tu :/# ... root@myu b u n tu :/# exit
Um den Container später wieder zu starten, können Sie jetzt myubuntu anstelle von hexadezimalen Codes oder verwirrenden Namenszusammensetzungen verwenden:
docker start -ai myubuntu
Optionen mit ein und zwei Bindestrichen
Beim vorigen Kommando docker run gibt es Optionen mit einem Bindestrich (-h) und solche mit zwei Bindestrichen (--name).
- Warum?
Traditionell ist es bei Linux-Kommandos üblich, die meisten Optionen in zwei Varianten anzugeben: Als Kurzschreibweise mit einem Buchstaben und einem vorangestellten Bindestrich, und in einer Variante mit ausführlichen Optionsnamen und zwei Bindestrichen.
- Anstelle von -h wäre auch --hostname zulässig.
- Wir ziehen in diesem Buch aus Platzgründen zumeist die Kurzschreibweise vor.
- Für --name gibt es allerdings keine Kurzschreibweise.
- Diese Option muss in der Langform übergeben werden.
Ein Sonderfall ist -it.
- Hierbei handelt es sich um zwei kurze Optionen, die kombiniert wurden. -it ist also eine Abkürzung für -i -t.
- Ebenso wäre -abc eine Kurzform für
-a -b -c. Eine vollständige Referenz aller Optionen für ein bestimmtes Kommando erhalten Sie unter macOS und Linux mit man, wobei Sie das Haupt- und das Subkommando in zwei Parametern übergeben können.
- Den Hilfetext zu docker run können Sie also mit man docker run lesen, bei Podman analog mit man podman run.
- Windows-Nutzer müssen stattdessen die Dokumentation im Online-Handbuch suchen, die sich für docker run bzw. podman run hier befindet:
- https://docs.docker.com/engine/reference/run
- https://docs.podman.io/en/latest/markdown/podman-run.1.html
Parallel weitere Prozesse mit docker exec ausführen
Häufig wird in einem Docker-Container nur ein Prozess ausgeführt – sei es eine interaktive Shell im Vordergrund wie in den vorigen Beispielen, sei es ein Serverdienst im Hintergrund.
- docker exec bietet Ihnen die Möglichkeit, parallel zu einem laufenden Container beliebige weitere Prozesse zu starten.
- docker exec ist primär zum Debugging gedacht, kann aber universell eingesetzt werden.
Das folgende Kommando, das in einem zweiten Termina- oder PowerShell-Fenster auszuführen ist, startet parallel zum bereits laufenden myubuntu -Container das Kommando top.
- Es wird ausgeführt, bis es durch (Q) beendet wird.
docker exec -it myubuntu / usr / bin / top
Sie können auch mehrere Shell-Sessions parallel ausführen:
docker exec -it myubuntu / bin / bash
Aufräumen
Vermutlich sind vom Experimentieren jetzt diverse Ubuntu-Container übrig geblieben.
- docker ps -a liefert einen Überblick über alle Container.
- In einem weiteren Kommando können Sie nun mit docker rm <name1> <name2> alle betreffenden Container löschen.
- In Abschnitt 3.9, »Administration«, zeigen wir Ihnen, wie Sie unter macOS und Linux mit einem einzigen Kommando sämtliche Container löschen können, die ein bestimmtes Image nutzen.
Prinzipiell könnten Sie nun mit docker image rm ubuntu auch das Ubuntu-Image löschen.
- Es ist aber gut möglich, dass Sie dieses Image später noch öfter brauchen werden.
- Wenn Sie jetzt auf das Löschen verzichten, ersparen Sie sich dann einen neuerlichen Download.
Portweiterleitung
Neben dem schon vorgestellten hello-world-Image gibt es im Docker Hub ein weiteres Image, das für erste Experimente gedacht ist.
- macOS- und Windows-Anwender werden nach der Installation von Docker Desktop unmissverständlich darauf hingewiesen, dieses Beispiel auszuprobieren.
- Wenn Sie sich nach der Installation dagegen entschieden haben oder wenn Sie das Beispiel unter Linux ausprobieren möchten, sind Sie in diesem Abschnitt richtig!
Container-Ports mit lokalen Ports verbinden
getting-started ist im Vergleich zu den bisherigen Beispielen dieses Kapitels insofern spannend, als es einen weiteren Aspekt der Docker-Anwendung ins Spiel bringt: die Integration von Containern in das lokale Netzwerk.
- Bei getting-started handelt es sich um einen einfachen Webserver, dessen Container als Hintergrunddienst ausgeführt wird.
- Sofern Sie Port 80 des Containers mit einem freien Port Ihres Host-Rechners verbinden (Option -p), können Sie über einen Webbrowser die vom Webserver zur Verfügung gestellten HTML-Dokumente lesen.
- Die Inbetriebnahme erfolgt Docker-typisch mit einem unscheinbaren, kurzen Kommando:
docker run -d -p 80:80 docker / getting - started
Kurz eine Erklärung der Optionen: -d (detach) bedeutet, dass Docker den Container im Hintergrund ausführen soll.
- Aufgrund von -p 80:80 verbindet Docker Port 80 des Containers mit Port 80 des lokalen Rechners.
Obwohl das getting-started -Image viele Docker-spezifische Anweisungen enthält, eignet es sich prinzipiell auch für Podman.
- Das Kommando sieht dann wie folgt aus
(warum jetzt Port 8080 im Spiel ist, erklären wir Ihnen gleich):
podman run -d -p 8080:80 docker .
- io / docker / getting - started
Sicherheitsrisiko durch Ports
Durch -p geöffnete Ports können nicht nur auf dem lokalen Rechner genutzt werden, sondern sind auch nach außen hin sichtbar! In manchen Fällen kann dies ein Sicherheitsrisiko sein.
- Dieses vermeiden Sie, wenn Sie die Port-Weiterleitung explizit auf localhost beschränken, z. B. mit docker run -p 127.0.0.1:8080:80 .
https://docs.docker.com/network
Offizielle Images
Im Unterschied zu den bisherigen Beispielen reicht es bei diesem Beispiel nicht, als Image-Name einfach nur getting-started anzugeben.
- Diese Kurzschreibweise ist nur für »offizielle« Images vorgesehen, die Basis-Images bzw. grundlegende Programmiersprachen, Server oder sonstige Tools zur Verfügung stellen.
Offizielle Images müssen bestimmte Spielregeln einhalten, werden dafür aber innerhalb des Docker Hubs bevorzugt behandelt: https://docs.docker.com/docker-hub/official_images Bei allen anderen Images, die von Entwicklern oder Firmen über den Docker Hub bereitgestellt werden, muss dem Image-Namen der Firmen- oder Entwicklername vorangestellt werden – hier also docker/getting-started.
Nach einigen Statusmeldungen (in der Regel muss Docker das Image zuerst herunterladen) passiert – scheinbar – nichts.
- docker hat das Kommando ausgeführt, aber anders als bei den bisherigen Beispielen gibt es kein visuelles Feedback in der Konsole.
- docker ps beweist immerhin, dass der Container tatsächlich läuft:
docker ps
CONTAINE R ID IMAGE PORTS ... 6 f3f1d532 6 5 9 docker / getting - started 0.0.0.0:80 - >80/tcp
Die Spalte PORTS verrät, dass Port 80 des Containers mit Port 80 des Docker-Hosts (also Ihres Rechners!) verbunden ist.
- Um zu sehen, was auf Port 80 passiert, öffnen Sie auf Ihrem Webbrowser die Adresse localhost. (Unter Umständen müssen Sie http://localhost eingeben, damit der Browser Ihre Eingabe nicht als Suchaufforderung versteht.) Damit kommen Sie auf eine Website, die der von Docker ausgeführte Container – genau genommen ein Webserver – zur Verfügung stellt (siehe Abbildung 3.1).
Die Website besteht aus einer ganzen Palette von Seiten, die durch ein weiteres Beispiel für die Anwendung von Docker führen.
- Dabei geht es um die Inbetriebnahme eines weiteren Containers auf der Basis eines zuvor lokal erstellten Images.
- Dieses heißt – ein wenig verwirrend – ebenfalls getting-started , wenn auch ohne vorangestelltes docker/.
- Wir empfehlen Ihnen, zuerst Kapitel 4, »Eigene Images«, zu lesen, bevor Sie der Anleitung des getting-started-Beispiels folgen.
Abbildung 3.1 Die »getting-started«-App im Webbrowser
Probleme mit Port 80
Nicht in jedem Fall führt das vorhin angegebene Kommando docker run zum Erfolg. Eine mögliche Fehlerursache kann darin bestehen, dass Port 80 schon belegt ist, weil auf Ihrem Rechner bereits ein Webserver aktiv ist.
- Gerade auf Entwicklungsrechnern ist das nicht ungewöhnlich.
- In diesem Fall verändern Sie die Optionen von docker run ein wenig und geben eben einen anderen Zielport an (hier 8080).
Beachten Sie die Syntax -p hostport:containerport ! Die erste Portnummer bezieht sich also auf den Host (auf Ihren Computer), die zweite auf den Container.
- Die Reihenfolge widerspricht der Quelle-Ziel-Logik der meisten Linux-Kommandos.
- Grundsätzlich gilt bei allen Docker-Optionen, die eine Zuordnung zwischen Host und Container festlegen (Ports, Volumes etc.), dass zuerst die Hostund dann die Container-Daten angegeben werden.
docker run -d -p 8080:80 docker / getting - started
Wenn das klappt, dann müssen Sie nun Port 8080 auch in der Adresse verwenden, die Sie in Ihrem Webbrowser angeben – also http://localhost:8080. Eine zweite Fehlerursache kann darin bestehen, dass Sie unter Linux mit Rootless Docker oder mit Podman arbeiten.
- Ohne root-Rechte kann Docker nicht über die
»privilegierten« Ports kleiner als 1024 verfügen.
- Der Lösungsweg ist der gleiche wie vorhin – Sie verwenden eben eine Portnummer, die größer ist als 1024 – z. B. 8080.
(Jede Zahl zwischen 1024 und 65535 funktioniert, sofern der Port nicht schon für eine andere Funktion reserviert ist.)
Aufräumen
Der getting-started-Container läuft im Hintergrund weiter, bis Sie ihn explizit beenden oder Ihren Rechner neu starten. (Wenn Sie mit Rootless Docker arbeiten, führt auch ein Logout dazu, dass die Container-Ausführung gestoppt wird.) Um die Container-Ausführung zu beenden, ermitteln Sie zuerst mit ps seinen Namen oder seine ID.
- In der Folge stoppen Sie den Container:
docker ps
CONTAINE R ID IMAGE ... NAMES 3 c8ac7126 2 b 8 docker / getting - started nervous_w i l l i am s
docker stop 3 c8ac71262 b 8
Wenn Sie denselben Container später noch einmal starten möchten, führen Sie entsprechend docker start <id> oder <name> aus.
- Die ID können Sie bei Bedarf mit docker ps -a ermitteln.
- Mit der Option -a listet docker ps alle Container auf, auch die, die gerade nicht ausgeführt werden.
docker rm <id> löscht den Container.
- Das funktioniert nur, wenn er nicht läuft.
- Gegebenenfalls führen Sie vorher docker stop aus oder übergeben docker rm die Option -f
(force), um den Container sowohl zu stoppen als auch zu löschen. Das Image löschen Sie mit docker image rm docker/getting-started.
- Das ist wiederum nur möglich, nachdem Sie vorher alle davon abgeleiteten Container gelöscht haben.