Führen Sie Ihren ersten Container aus

DockerDockerBeginner
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab werden Sie Ihren ersten Docker-Container ausführen.

Container sind einfach ein Prozess (oder eine Gruppe von Prozessen), der in Isolation läuft. Die Isolation wird über Linux-Namespaces, Control Groups (cgroups), seccomp und SELinux erreicht. Beachten Sie, dass Linux-Namespaces und Control Groups in den Linux-Kernel integriert sind! Abgesehen vom Linux-Kernel selbst ist es ansonsten nichts Besonderes an Containern.

Was Containern nützlich macht, ist die Tooling, die sich um sie herum entwickelt hat. Für diese Labs werden wir Docker verwenden, das ein weit verbreitetes Tool zur Verwendung von Containern zum Erstellen von Anwendungen ist. Docker bietet Entwicklern und Betreibern eine freundliche Schnittstelle, um Container auf jeder Umgebung mit einem Docker-Engine zu erstellen, zu verschiffen und auszuführen. Da der Docker-Client einen Docker-Engine erfordert, ist eine Alternative die Verwendung von Podman, einem daemonlosen Container-Engine, um OCI-Container zu entwickeln, zu verwalten und auszuführen und um Container als root oder im rootless-Modus auszuführen. Aus diesen Gründen empfehlen wir Podman, aber aufgrund der Verbreitung wird in diesem Lab immer noch Docker verwendet.

Im ersten Teil dieses Labs werden wir unseren ersten Container ausführen und lernen, wie wir ihn untersuchen können. Wir werden die Namespace-Isolation, die wir aus dem Linux-Kernel erhalten, beobachten können.

Nachdem wir unseren ersten Container ausgeführt haben, werden wir uns anderen Anwendungen von Containern widmen. Sie können viele Beispiele davon im Docker Store finden, und wir werden mehrere verschiedene Typen von Containern auf dem gleichen Host ausführen. Dies wird uns die Vorteile der Isolation zeigen - dass wir mehrere Container auf dem gleichen Host ohne Konflikte ausführen können.

Wir werden in diesem Lab einige Docker-Befehle verwenden. Für die vollständige Dokumentation zu den verfügbaren Befehlen schauen Sie sich die offizielle Dokumentation an.

Dies ist ein Guided Lab, das schrittweise Anweisungen bietet, um Ihnen beim Lernen und Üben zu helfen. Befolgen Sie die Anweisungen sorgfältig, um jeden Schritt abzuschließen und praktische Erfahrungen zu sammeln. Historische Daten zeigen, dass dies ein Labor der Stufe Anfänger mit einer Abschlussquote von 90% ist. Es hat eine positive Bewertungsrate von 92% von den Lernenden erhalten.

Erste Schritte

Öffnen Sie ein Terminal auf der LabEx VM und führen Sie docker -h aus, um die Hilfeseite für die Docker-Befehlszeilenschnittstelle (CLI) anzuzeigen.

$ docker -h
Flag shorthand -h has been deprecated, please use --help

Usage: docker [OPTIONS] COMMAND

A self-sufficient runtime for containers

...

Management Commands:
builder Manage builds
config Manage Docker configs
container Manage containers
engine Manage the docker engine
image Manage images
network Manage networks
node Manage Swarm nodes
plugin Manage plugins
secret Manage Docker secrets
service Manage services
stack Manage Docker stacks
swarm Manage Swarm
system Manage Docker
trust Manage trust on Docker images
volume Manage volumes

Die Docker-Befehlszeilenschnittstelle kann verwendet werden, um mehrere Funktionen des Docker-Engines zu verwalten. In diesem Lab werden wir uns hauptsächlich auf den container-Befehl konzentrieren.

Installieren Sie podman auf Ihrer LabEx VM.

sudo apt-get update
sudo apt-get install podman -y

Wenn podman installiert ist, können Sie den alternativen Befehl ausführen, um ihn zu vergleichen.

sudo podman -h

Sie können zusätzlich die Version Ihrer Docker-Installation mit docker version überprüfen

docker version

Client:
Version: 20.10.21
...

Server:
Engine:
Version: 20.10.21
...

Sie stellen fest, dass Docker sowohl einen Client als auch einen Server: Docker Engine installiert. Wenn Sie beispielsweise den gleichen Befehl für podman ausführen, werden Sie nur eine CLI-Version sehen, da podman daemonlos läuft und auf eine OCI-kompatible Containerlaufzeit (runc, crun, runv etc.) zurückgreift, um mit dem Betriebssystem zu interagieren und die laufenden Container zu erstellen.

sudo podman version --events-backend=none
Version: 3.4.4
API Version: 3.4.4
Go Version: go1.17.3
Built: Thu Jan 1 08:00:00 1970
OS/Arch: linux/amd64

Führen Sie Ihren ersten Container aus

Wir werden die Docker-Befehlszeilenschnittstelle (CLI) verwenden, um unseren ersten Container auszuführen.

Öffnen Sie ein Terminal auf der LabEx VM.

Führen Sie den Befehl aus.

docker container run -t ubuntu top

Verwenden Sie den Befehl docker container run, um einen Container mit dem ubuntu-Bild mithilfe des top-Befehls auszuführen. Das Flag -t weist einen Pseudo-TTY zu, den wir für die korrekte Funktion von top benötigen.

$ docker container run -it ubuntu top
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
aafe6b5e13de: Pull complete
0a2b43a72660: Pull complete
18bdd1e546d2: Pull complete
8198342c3e05: Pull complete
f56970a44fd4: Pull complete
Digest: sha256:f3a61450ae43896c4332bda5e78b453f4a93179045f20c8181043b26b5e79028
Status: Downloaded newer image for ubuntu:latest

Der Befehl docker run führt zunächst einen docker pull aus, um das ubuntu-Bild auf Ihren Host herunterzuladen. Nachdem es heruntergeladen ist, startet es den Container. Die Ausgabe für den laufenden Container sollte so aussehen:

top - 20:32:46 up 3 days, 17:40,  0 users,  load average: 0.00, 0.01, 0.00
Tasks:   1 total,   1 running,   0 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.1 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  2046768 total,   173308 free,   117248 used,  1756212 buff/cache
KiB Swap:  1048572 total,  1048572 free,        0 used.  1548356 avail Mem

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
      1 root      20   0   36636   3072   2640 R   0.3  0.2   0:00.04 top

top ist ein Linux-Werkzeug, das die Prozesse auf einem System ausgibt und sie nach der Ressourcenverbrauch sortiert. Beachten Sie, dass in dieser Ausgabe nur ein einziger Prozess ist: es ist der top-Prozess selbst. Wir sehen in dieser Liste keine anderen Prozesse von unserem Host, da aufgrund der PID-Namespace-Isolation.

Container verwenden Linux-Namespaces, um die Isolation von Systemressourcen von anderen Containern oder dem Host zu gewährleisten. Der PID-Namespace bietet Isolation für Prozess-IDs. Wenn Sie top innerhalb des Containers ausführen, werden Sie feststellen, dass es die Prozesse innerhalb des PID-Namespace des Containers zeigt, was sich stark unterscheidet von dem, was Sie sehen würden, wenn Sie top auf dem Host ausgeführt hätten.

Auch wenn wir das ubuntu-Bild verwenden, ist es wichtig zu beachten, dass unser Container keinen eigenen Kernel hat. Er verwendet den Kernel des Hosts, und das ubuntu-Bild wird nur verwendet, um das Dateisystem und die Tools zur Verfügung zu stellen, die auf einem Ubuntu-System verfügbar sind.

Untersuchen Sie den Container mit docker container exec

Der Befehl docker container exec ist eine Möglichkeit, mit einem neuen Prozess in die Namespaces eines laufenden Containers einzutauchen.

Öffnen Sie ein neues Terminal. Wählen Sie Terminal > New Terminal.

Im neuen Terminal verwenden Sie den Befehl docker container ls, um die ID des gerade erstellten laufenden Containers zu erhalten.

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b3ad2a23fab3 ubuntu "top" 29 minutes ago Up 29 minutes goofy_nobel

Verwenden Sie dann diese ID, um bash innerhalb dieses Containers mithilfe des Befehls docker container exec auszuführen. Da wir bash verwenden und mit diesem Container von unserem Terminal interagieren möchten, verwenden wir die Flags -it, um im interaktiven Modus auszuführen, während ein Pseudo-Terminal zugewiesen wird.

$ docker container exec -it ID < CONTAINER > bash
root@b3ad2a23fab3:/#

Und voilà! Wir haben gerade den Befehl docker container exec verwendet, um mit unserem bash-Prozess in die Namespaces unseres Containers einzutauchen. Das Verwenden von docker container exec mit bash ist ein häufiges Muster, um einen Docker-Container zu untersuchen.

Beachten Sie die Änderung am Präfix Ihres Terminals. z.B. root@b3ad2a23fab3:/. Dies ist ein Hinweis darauf, dass wir bash "innerhalb" unseres Containers ausführen.

Hinweis: Dies ist nicht dasselbe wie das SSH in einen separaten Host oder eine VM. Wir brauchen keinen SSH-Server, um mit einem bash-Prozess zu verbinden. Denken Sie daran, dass Container kernelbasierte Funktionen verwenden, um Isolation zu erreichen, und dass Container auf dem Kernel laufen. Unser Container ist einfach eine Gruppe von Prozessen, die in Isolation auf dem gleichen Host laufen, und wir können docker container exec verwenden, um mit dem bash-Prozess in diese Isolation einzutauchen. Nachdem docker container exec ausgeführt wurde, umfasst die Gruppe von Prozessen, die in Isolation laufen (d.h. unser Container), top und bash.

Im selben Terminal führen Sie ps -ef aus, um die laufenden Prozesse zu untersuchen.

root@b3ad2a23fab3:/## ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 20:34? 00:00:00 top
root 17 0 0 21:06? 00:00:00 bash
root 27 17 0 21:14? 00:00:00 ps -ef

Sie sollten nur den top-Prozess, den bash-Prozess und unseren ps-Prozess sehen.

Zum Vergleich verlassen Sie den Container und führen Sie ps -ef oder top auf dem Host aus. Diese Befehle funktionieren auf Linux oder Mac. Für Windows können Sie die laufenden Prozesse mit tasklist untersuchen.

root@b3ad2a23fab3:/## exit
exit
$ ps -ef
## Lots of processes!

Technischer Tieftauchen
PID ist nur einer der Linux-Namespaces, der Containern die Isolation von Systemressourcen bietet. Andere Linux-Namespaces umfassen:

  • MNT - Mounten und Entfernen von Verzeichnissen ohne die anderen Namespaces zu beeinflussen
  • NET - Container haben ihren eigenen Netzwerkstack
  • IPC - Isolierte interprozessuale Kommunikationsmechanismen wie Nachrichtenwarteschlangen.
  • User - Isolierter Ansicht der Benutzer auf dem System
  • UTC - Setzen Sie den Hostnamen und die Domäne pro Container

Diese Namespaces bieten zusammen die Isolation für Container, die es ihnen ermöglichen, gemeinsam sicher zu laufen und ohne Konflikt mit anderen Containern, die auf dem gleichen System laufen. Als Nächstes werden wir verschiedene Anwendungen von Containern demonstrieren und den Vorteil der Isolation, wenn wir mehrere Container auf dem gleichen Host ausführen.

Hinweis: Namespaces sind eine Funktion des Linux-Kernels. Aber Docker ermöglicht es Ihnen, Container auf Windows und Mac auszuführen... wie funktioniert das? Das Geheimnis ist, dass in das Docker-Produkt oder den Docker-Engine ein Linux-Subsystem eingebettet ist. Docker hat dieses Linux-Subsystem in ein neues Projekt open-sourced: LinuxKit. Ein Vorteil der Verwendung der Docker-Tooling mit Containern ist, dass Sie Container auf vielen verschiedenen Plattformen ausführen können.

Zusätzlich zu der Ausführung von Linux-Containern auf Windows mithilfe eines Linux-Subsystems sind native Windows-Container jetzt möglich, dank der Erstellung von Container-Primitiven auf dem Windows-OS. Native Windows-Container können auf Windows 10 oder Windows Server 2016 oder neuer ausgeführt werden.

Hinweis: Wenn Sie diese Übung in einem containerisierten Terminal ausführen und den Befehl ps -ef im Terminal ausführen, werden Sie nach dem Beenden des exec-Befehls immer noch eine begrenzte Anzahl von Prozessen sehen. Sie können versuchen, den Befehl ps -ef in einem Terminal auf Ihrem lokalen Computer auszuführen, um alle Prozesse zu sehen.

Bereinigen Sie den Container, der die top-Prozesse ausführt, indem Sie <ctrl>-c drücken, listen Sie alle Container auf und entfernen Sie die Container anhand ihrer ID.

docker ps -a

docker rm <CONTAINER ID>

Führen Sie mehrere Container aus

Entdecken Sie den Docker Hub

Der Docker Hub ist das zentrale öffentliche Registrierungssystem für Docker-Images, das Community- und offizielle Images enthält.

Wenn Sie nach Images suchen, finden Sie Filter für "Docker Certified", "Verified Publisher" und "Official Images". Wählen Sie den Filter "Docker Certified", um Images zu finden, die als enterprise-fähig angesehen werden und mit dem Docker Enterprise Edition-Produkt getestet wurden. Es ist wichtig, unverifizierten Inhalt aus dem Docker Store zu vermeiden, wenn Sie eigene Images entwickeln, die in die Produktionsumgebung bereitgestellt werden sollen. Diese unverifizierten Images können Sicherheitslücken oder sogar Schadsoftware enthalten.

Im zweiten Schritt dieses Labs werden wir einige Container starten, die von verifizierten Images aus dem Docker Hub stammen: einen Nginx-Webserver und eine MongoDB-Datenbank.

Führen Sie einen Nginx-Server aus

Lassen Sie uns einen Container mit dem offiziellen Nginx-Image aus dem Docker Hub starten.

docker container run --detach --publish 8080:80 --name nginx nginx

Wir verwenden hier einige neue Flags. Das Flag --detach wird diesen Container im Hintergrund ausführen. Das publish-Flag veröffentlicht den Port 80 im Container (der Standardport für Nginx) über den Port 8080 auf unserem Host. Denken Sie daran, dass der NET-Namespace den Prozessen des Containers einen eigenen Netzwerkstack gibt. Das --publish-Flag ist eine Funktion, die uns ermöglicht, das Netzwerk durch den Container auf den Host zu exponieren.

Wie wissen Sie, dass Port 80 der Standardport für Nginx ist? Weil er in der Dokumentation auf dem Docker Hub aufgeführt ist. Im Allgemeinen ist die Dokumentation für die verifizierten Images sehr gut, und Sie sollten sich auf sie beziehen, wenn Sie Container mit diesen Images ausführen.

Wir geben auch das --name-Flag an, das den Container benennt. Jeder Container hat einen Namen. Wenn Sie keinen angeben, wird Ihnen Docker einen zufällig zuweisen. Die Angabe Ihres eigenen Namens erleichtert es Ihnen, spätere Befehle auf Ihrem Container auszuführen, da Sie den Namen statt der ID des Containers referenzieren können. Beispielsweise: docker container inspect nginx statt docker container inspect 5e1.

Da dies der erste Versuch ist, den Nginx-Container auszuführen, wird das Nginx-Image aus dem Docker Store heruntergeladen. Später erstellte Container aus dem Nginx-Image werden das vorhandene Image auf Ihrem Host verwenden.

Nginx ist ein leichter Webserver. Sie können den Nginx-Server auf der Registerkarte Web 8080 der LabEx VM zugreifen. Wechseln Sie zu ihr und aktualisieren Sie die Seite, um die Ausgabe von Nginx zu sehen.

Schritt 2 Nginx

Führen Sie einen mongo-DB-Server aus

Jetzt starten wir einen MongoDB-Server. Wir werden das offizielle MongoDB-Image aus dem Docker Hub verwenden. Anstatt das latest-Tag zu verwenden (der Standard ist, wenn kein Tag angegeben wird), verwenden wir eine bestimmte Version des mongo-Images: 4.4.

docker container run --detach --publish 8081:27017 --name mongo mongo:4.4

Auch hier wird das mongo-Image aus dem Docker Store heruntergeladen, da es der erste Versuch ist, einen mongo-Container auszuführen. Wir verwenden das --publish-Flag, um den mongo-Port 27017 auf unserem Host zu exponieren. Wir müssen einen anderen Port als 8080 für die Hostzuordnung verwenden, da dieser Port bereits auf unserem Host exponiert ist. Wenden Sie sich erneut an die offiziellen Dokumentationen auf dem Docker Hub, um weitere Details zur Verwendung des mongo-Images zu erhalten.

Sehen Sie die Ausgabe von MongoDB im Webbrowser unter 0.0.0.0:8081. Sie sollten eine Meldung sehen, die eine Warnung von MongoDB zurückgibt.

MongoDB-Serverausgabe - Warnung

Überprüfen Sie Ihre laufenden Container mit docker container ls

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6777df89fea nginx "nginx -g 'daemon..." Weniger als eine Sekunde ago Up 2 Sekunden 0.0.0.0:8080- nginx > 80/tcp
ead80a0db505 mongo "docker-entrypoint..." 17 Sekunden ago Up 19 Sekunden 0.0.0.0:8081- mongo > 27017/tcp
af549dccd5cf ubuntu "top" 5 Minuten ago Up 5 Minuten priceless_kepler

Sie sollten sehen, dass Sie einen Nginx-Webserver-Container und einen MongoDB-Container auf Ihrem Host ausführen. Beachten Sie, dass wir diese Container nicht so konfiguriert haben, dass sie miteinander kommunizieren.

Sie können die Namen "nginx" und "mongo" sehen, die wir unseren Containern gegeben haben, und den zufälligen Namen (in meinem Fall "priceless_kepler"), der für den ubuntu-Container generiert wurde. Sie können auch sehen, die Portzuordnungen, die wir mit dem --publish-Flag angegeben haben. Für weitere Details zu diesen laufenden Containern können Sie den Befehl docker container inspect [container id verwenden.

Eines, das Sie vielleicht bemerken, ist, dass der mongo-Container die docker-entrypoint-Befehl ausführt. Dies ist der Name des ausführbaren Programms, das beim Start des Containers ausgeführt wird. Das mongo-Image erfordert einige Vorkonfiguration, bevor der Datenbankprozess gestartet wird. Sie können genau sehen, was das Skript macht, indem Sie es auf github ansehen. Normalerweise können Sie den Link zur github-Quelle von der Bildbeschreibungsseite auf der Docker Store-Website finden.

Container sind selbst enthalten und isoliert, was bedeutet, dass wir potenzielle Konflikte zwischen Containern mit unterschiedlichen System- oder Laufzeitabhängigkeiten vermeiden können. Beispielsweise: die Bereitstellung einer App, die Java 7 verwendet, und einer anderen App, die Java 8 verwendet, auf dem gleichen Host. Oder das Ausführen mehrerer Nginx-Container, die alle Port 80 als Standardhörtport haben (wenn Sie ihn auf dem Host mit dem --publish-Flag exponieren, müssen die für den Host ausgewählten Ports eindeutig sein). Die Isolationsvorteile sind möglich aufgrund von Linux-Namespaces.

Hinweis: Sie mussten nichts auf Ihrem Host installieren (außer Docker), um diese Prozesse auszuführen! Jeder Container enthält die Abhängigkeiten, die er innerhalb des Containers benötigt, so dass Sie nichts direkt auf Ihrem Host installieren müssen.

Das Ausführen mehrerer Container auf demselben Host ermöglicht es uns, die verfügbaren Ressourcen (CPU, Arbeitsspeicher usw.) auf einem einzelnen Host optimal zu nutzen. Dies kann zu erheblichen Kosteneinsparungen für ein Unternehmen führen.

Während das direkte Ausführen von Images aus dem Docker Hub manchmal nützlich sein kann, ist es nützlicher, eigene benutzerdefinierte Images zu erstellen und auf offizielle Images als Ausgangspunkt für diese Bilder zu verweisen. Wir werden uns in Lab 2 mit dem Erstellen unserer eigenen benutzerdefinierten Images befassen.

Bereinigen

Wenn Sie dieses Lab abschließen, verbleiben auf Ihrem Host eine Reihe von laufenden Containern. Lassen Sie uns diese bereinigen.

Zunächst erhalten Sie eine Liste der laufenden Container mit docker container ls.

$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6777df89fea nginx "nginx -g 'daemon..." 3 Minuten ago Up 3 Minuten 0.0.0.0:8080- nginx > 80/tcp
ead80a0db505 mongo "docker-entrypoint..." 3 Minuten ago Up 3 Minuten 0.0.0.0:8081- mongo > 27017/tcp
af549dccd5cf ubuntu "top" 8 Minuten ago Up 8 Minuten priceless_kepler

Als nächstes führen Sie docker container stop [container id] für jeden Container in der Liste aus. Sie können auch die Namen der Container verwenden, die Sie zuvor angegeben haben.

$ docker container stop d67 ead af5
d67
ead
af5

Hinweis: Sie müssen nur so viele Ziffern der ID angeben, dass sie eindeutig ist. Drei Ziffern reichen in der Regel aus.

Entfernen Sie die gestoppten Container

docker system prune ist ein wirklich praktischer Befehl, um Ihr System zu bereinigen. Er wird alle gestoppten Container, nicht genutzte Volumes und Netzwerke sowie hängende Bilder entfernen.

$ docker system prune
WARNING! This will remove:
- all stopped containers
- all volumes not used by at least one container
- all networks not used by at least one container
- all dangling images
Are you sure you want to continue? [y/N] y
Deleted Containers:
7872fd96ea4695795c41150a06067d605f69702dbcb9ce49492c9029f0e1b44b
60abd5ee65b1e2732ddc02b971a86e22de1c1c446dab165462a08b037ef7835c
31617fdd8e5f584c51ce182757e24a1c9620257027665c20be75aa3ab6591740

Total reclaimed space: 12B

Zusammenfassung

In diesem Lab haben Sie Ihre ersten Ubuntu-, Nginx- und MongoDB-Container erstellt.

Wichtige Erkenntnisse

  • Container bestehen aus Linux-Namespaces und Kontrollgruppen, die Isolation von anderen Containern und dem Host gewährleisten.
  • Aufgrund der Isolationseigenschaften von Containern können Sie viele Container auf einem einzelnen Host planen, ohne sich um konfligierende Abhängigkeiten zu sorgen. Dies erleichtert es, mehrere Container auf einem einzelnen Host auszuführen: die zu diesem Host zugewiesenen Ressourcen optimal zu nutzen und letztendlich Kosten für Server zu sparen.
  • Vermeiden Sie die Verwendung unverifizierten Inhalts aus dem Docker Store, wenn Sie eigene Bilder entwickeln, da diese Bilder möglicherweise Sicherheitslücken oder sogar Schadsoftware enthalten können.
  • Container enthalten alles, was sie zur Ausführung der Prozesse innerhalb von ihnen benötigen, sodass es nicht erforderlich ist, zusätzliche Abhängigkeiten direkt auf Ihrem Host zu installieren.