Wie man den docker compose run Befehl für einmalige Aufgaben verwendet

DockerDockerBeginner
Jetzt üben

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

Einführung

In diesem Lab lernen Sie, wie Sie den Befehl docker compose run effektiv nutzen können, um einmalige Aufgaben in Ihren Docker Compose Services auszuführen. Dies ist eine leistungsstarke Technik, um administrative Befehle auszuführen, Debugging durchzuführen oder spezifische Operationen durchzuführen, ohne den gesamten Service-Stack zu starten.

Wir werden verschiedene Szenarien untersuchen, darunter das Überschreiben des Standard-Service-Befehls, das Aktivieren von Service-Ports für die Interaktion, manuelles Port-Mapping, das Ausführen von Befehlen ohne verknüpfte Services zu starten und das automatische Entfernen des Containers nach der Ausführung. Am Ende dieses Labs werden Sie in der Lage sein, docker compose run für verschiedene einmalige Aufgaben sicher anzuwenden.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/NetworkOperationsGroup(["Network Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ps("List Running Containers") docker/ContainerOperationsGroup -.-> docker/stop("Stop Container") docker/ContainerOperationsGroup -.-> docker/rm("Remove Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/NetworkOperationsGroup -.-> docker/network("Manage Networks") subgraph Lab Skills docker/run -.-> lab-555091{{"Wie man den docker compose run Befehl für einmalige Aufgaben verwendet"}} docker/ps -.-> lab-555091{{"Wie man den docker compose run Befehl für einmalige Aufgaben verwendet"}} docker/stop -.-> lab-555091{{"Wie man den docker compose run Befehl für einmalige Aufgaben verwendet"}} docker/rm -.-> lab-555091{{"Wie man den docker compose run Befehl für einmalige Aufgaben verwendet"}} docker/pull -.-> lab-555091{{"Wie man den docker compose run Befehl für einmalige Aufgaben verwendet"}} docker/network -.-> lab-555091{{"Wie man den docker compose run Befehl für einmalige Aufgaben verwendet"}} end

Ausführen eines einmaligen Befehls mit Überschreibung des Service-Befehls

In diesem Schritt lernen Sie, wie Sie einen einmaligen Befehl in einem Docker-Container ausführen können, wobei der Standardbefehl des Docker-Images oder Dockerfiles überschrieben wird. Dies ist nützlich, um administrative Aufgaben durchzuführen, Debugging zu betreiben oder spezifische Skripte in der Container-Umgebung auszuführen, ohne den Hauptservice zu starten.

Zuerst laden wir ein einfaches Docker-Image herunter, das wir für diese Demonstration verwenden können. Wir verwenden das ubuntu-Image.

docker pull ubuntu:latest

Sie sollten eine Ausgabe sehen, die anzeigt, dass das Image heruntergeladen wird.

Using default tag: latest
latest: Pulling from library/ubuntu
...
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest

Nun führen wir einen einmaligen Befehl in einem Container basierend auf dem ubuntu-Image aus. Wir verwenden den Befehl docker run mit dem Image-Namen und dem auszuführenden Befehl. Beispielsweise führen wir den Befehl ls -l / aus, um den Inhalt des Root-Verzeichnisses im Container aufzulisten.

docker run ubuntu ls -l /

Dieser Befehl erstellt einen neuen Container aus dem ubuntu-Image, führt den Befehl ls -l / darin aus und beendet sich anschließend. Sie sollten eine ähnliche Ausgabe sehen, die den Inhalt des Root-Verzeichnisses anzeigt:

total 68
drwxr-xr-x   2 root root  4096 Oct 26 00:00 bin
drwxr-xr-x   2 root root  4096 Oct 26 00:00 boot
drwxr-xr-x   5 root root   360 Nov  1 00:00 dev
drwxr-xr-x  19 root root  4096 Nov  1 00:00 etc
drwxr-xr-x   2 root root  4096 Oct 26 00:00 home
drwxr-xr-x   7 root root  4096 Oct 26 00:00 lib
drwxr-xr-x   2 root root  4096 Oct 26 00:00 lib64
drwxr-xr-x   2 root root  4096 Oct 26 00:00 media
drwxr-xr-x   2 root root  4096 Oct 26 00:00 mnt
drwxr-xr-x   2 root root  4096 Oct 26 00:00 opt
drwxr-xr-x   2 root root  4096 Oct 04 14:00 proc
drwx------   2 root root  4096 Oct 26 00:00 root
drwxr-xr-x   2 root root  4096 Oct 26 00:00 run
drwxr-xr-x   2 root root  4096 Oct 26 00:00 sbin
drwxr-xr-x   2 root root  4096 Oct 26 00:00 srv
drwxr-xr-x   2 root root  4096 Oct 26 00:00 sys
drwxrwxrwt   2 root root  4096 Oct 26 00:00 tmp
drwxr-xr-x  11 root root  4096 Oct 26 00:00 usr
drwxr-xr-x  12 root root  4096 Oct 26 00:00 var

In diesem Fall ist der Standardbefehl des ubuntu-Images typischerweise eine Shell wie /bin/bash. Indem wir ls -l / nach dem Image-Namen angeben, weisen wir Docker an, diesen spezifischen Befehl anstelle des Standardbefehls auszuführen.

Lassen Sie uns einen weiteren Befehl ausprobieren, z. B. pwd, um das aktuelle Arbeitsverzeichnis im Container anzuzeigen.

docker run ubuntu pwd

Die Ausgabe sollte / sein, was darauf hinweist, dass das Root-Verzeichnis das standardmäßige Arbeitsverzeichnis ist.

/

Dies zeigt, wie Sie einfach beliebige Befehle in einem Container ausführen können, ohne interaktiv in den Container einzusteigen oder den Standardbefehl des Images zu ändern.

Ausführen eines Befehls mit aktivierten Service-Ports

In diesem Schritt untersuchen wir, wie ein Befehl in einem Docker-Container ausgeführt werden kann, während gleichzeitig die Ports aktiviert bleiben, die der Service im Container freigeben soll. Dies ist nützlich, wenn Sie einen temporären Befehl für Debugging- oder Administrationszwecke ausführen müssen, aber der Hauptservice dennoch von außerhalb des Containers erreichbar sein soll.

Für diese Demonstration verwenden wir ein einfaches Web-Server-Image. Lassen Sie uns das nginx-Image pullen, einen beliebten Web-Server.

docker pull nginx:latest

Sie sollten eine Ausgabe sehen, die anzeigt, dass das Image heruntergeladen wird.

Using default tag: latest
latest: Pulling from library/nginx
...
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

Das standardmäßige nginx-Image ist so konfiguriert, dass es innerhalb des Containers auf Port 80 lauscht. Um diesen Port von unserem Host-System aus erreichbar zu machen, müssen wir einen Host-Port auf den Container-Port mappen, indem wir das Flag -p mit dem docker run-Befehl verwenden. Lassen Sie uns Host-Port 8080 auf Container-Port 80 mappen.

Anstatt den standardmäßigen Nginx-Service zu starten, führen wir nun einen einfachen Befehl wie echo "Hello from the container" aus, während die Port-Mapping-Einstellung aktiv bleibt.

docker run -p 8080:80 nginx echo "Hello from the container"

Man könnte erwarten, dass dies den Nginx-Server startet und dann "Hello from the container" ausgibt. Wenn Sie jedoch nach dem Image-Namen in docker run einen Befehl angeben, ersetzt dieser Befehl den Standardbefehl. In diesem Fall führt der Container also den echo-Befehl aus und beendet sich anschließend. Der Nginx-Server wird nicht gestartet, obwohl wir das Port-Mapping angegeben haben.

Die Ausgabe wird einfach sein:

Hello from the container

Wenn Sie versuchen, http://localhost:8080 in Ihrem Webbrowser oder mit curl aufzurufen, werden Sie feststellen, dass die Verbindung abgelehnt wird, weil der Nginx-Server nicht läuft.

curl http://localhost:8080

Die Ausgabe wird wahrscheinlich sein:

curl: (7) Failed to connect to localhost port 8080 after ... connection refused

Dies verdeutlicht einen wichtigen Punkt: Wenn Sie den Standardbefehl mit docker run <image> <command> überschreiben, führt der Container nur den angegebenen Befehl aus und startet nicht den Service, für den das Image vorgesehen ist. Daher ist das Port-Mapping zwar konfiguriert, aber nicht aktiv, weil der Service, der auf diesem Port lauschen soll, nicht läuft.

Um einen Befehl auszuführen, während der Service läuft und seine Ports aktiv sind, würden Sie den Service typischerweise im Hintergrund starten und dann Ihren Befehl ausführen. Der docker run-Befehl ist jedoch dafür ausgelegt, einen einzelnen Befehl auszuführen und sich dann zu beenden. Um einen Befehl parallel zu einem laufenden Service auszuführen, würden Sie normalerweise docker exec auf einem Container verwenden, der den Service bereits ausführt. Dies werden wir in einem späteren Schritt untersuchen.

Das wichtigste Ergebnis dieses Schritts ist das Verständnis, dass die Angabe eines Befehls für docker run den Standard-Entrypoint/Befehl überschreibt und somit der standardmäßig konfigurierte Service nicht gestartet wird, selbst wenn Port-Mappings angegeben sind.

Ausführen eines Befehls mit manuellem Port-Mapping

In diesem Schritt untersuchen wir weiterhin das Port-Mapping mit docker run, wobei wir uns darauf konzentrieren, wie Host- und Container-Ports explizit angegeben werden können. Während der vorherige Schritt gezeigt hat, dass das Überschreiben des Standardbefehls den Start des Services verhindert, ist das Verständnis des manuellen Port-Mappings entscheidend, wenn Sie den Service tatsächlich erreichbar machen möchten.

Wir verwenden weiterhin das nginx-Image. Zur Erinnerung: Das nginx-Image macht Port 80 innerhalb des Containers verfügbar. Um diesen von unserem Host-System aus erreichbar zu machen, verwenden wir das Flag -p gefolgt von host_port:container_port.

Lassen Sie uns den nginx-Container starten und Host-Port 8081 auf Container-Port 80 mappen. Diesmal geben wir keinen überschreibenden Befehl an, sodass der standardmäßige Nginx-Service startet. Wir führen ihn zudem im Detached-Modus (-d) aus, sodass er im Hintergrund läuft.

docker run -d -p 8081:80 nginx

Sie sollten eine lange Zeichenkette sehen, die die Container-ID darstellt und anzeigt, dass der Container im Detached-Modus gestartet wurde.

<container_id>

Da der Container nun läuft und der Port gemappt ist, können Sie die Nginx-Begrüßungsseite von Ihrem Host-System aus mit curl oder einem Webbrowser aufrufen.

curl http://localhost:8081

Sie sollten den HTML-Inhalt der standardmäßigen Nginx-Begrüßungsseite sehen. Dies bestätigt, dass der Nginx-Server im Container läuft und von Ihrem Host-System über Port 8081 erreichbar ist.

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</body>
</html>

Dies zeigt, wie manuelles Port-Mapping Ihnen die Kontrolle darüber gibt, welcher Host-Port verwendet wird, um auf einen Service zuzugreifen, der auf einem bestimmten Port innerhalb eines Containers läuft. Dies ist entscheidend, um Port-Konflikte auf Ihrem Host-System zu vermeiden und containerisierte Services erreichbar zu machen.

Um den laufenden Container zu stoppen, können Sie den Befehl docker stop gefolgt von der Container-ID oder dem Namen verwenden. Die Container-ID finden Sie mit docker ps.

docker ps

Dies zeigt Ihnen eine Liste der laufenden Container. Suchen Sie die Container-ID für den gerade gestarteten nginx-Container.

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                  NAMES
<container_id>   nginx     "nginx -g 'daemon off"   About a minute ago   Up About a minute   0.0.0.0:8081->80/tcp   <container_name>

Stoppen Sie nun den Container mit seiner ID. Ersetzen Sie <container_id> durch die tatsächliche ID aus Ihrer Ausgabe.

docker stop <container_id>

Die Container-ID wird erneut ausgegeben, was bestätigt, dass der Container gestoppt wurde.

<container_id>

Wenn Sie nach dem Stoppen des Containers erneut versuchen, auf http://localhost:8081 zuzugreifen, wird die Verbindung abgelehnt.

Befehl ausführen ohne verknüpfte Dienste zu starten

In diesem Schritt lernen wir, wie man einen Befehl in einem Docker-Container ausführt, der Teil einer Multi-Container-Anwendung ist, ohne die anderen verknüpften Dienste zu starten. Dies ist besonders nützlich für Datenbank-Migrationen, Setup-Skripte oder Debugging-Befehle in einem Service, ohne den gesamten Anwendungsstack hochfahren zu müssen.

Während Docker Compose das Standard-Tool für die Verwaltung von Multi-Container-Anwendungen ist und Funktionen für einmalige Befehle in bestimmten Services bietet, demonstrieren wir hier die zugrundeliegenden Docker-Konzepte. Da Docker Compose in dieser Umgebung nicht vorinstalliert ist, konzentrieren wir uns auf die Verwendung des docker run-Befehls mit Netzwerkfunktionen.

Lassen Sie uns ein einfaches Szenario mit zwei Containern simulieren: einer Webanwendung und einer Datenbank. Wir verwenden ein generisches ubuntu-Image für unsere Webanwendung und ein postgres-Image für die Datenbank.

Zuerst pullen wir das postgres-Image:

docker pull postgres:latest

Sie sollten eine Ausgabe sehen, die anzeigt, dass das Image heruntergeladen wird.

Using default tag: latest
latest: Pulling from library/postgres
...
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest

Nun erstellen wir ein Docker-Netzwerk, damit unsere Container über Namen miteinander kommunizieren können.

docker network create my-app-network

Sie sollten die Netzwerk-ID ausgegeben sehen.

<network_id>

Als nächstes starten wir den postgres-Container und verbinden ihn mit unserem Netzwerk. Wir setzen auch ein Passwort für den PostgreSQL-Benutzer.

docker run -d --network my-app-network --name my-database -e POSTGRES_PASSWORD=mypassword postgres

Sie sollten die Container-ID sehen, was anzeigt, dass der Datenbank-Container im Hintergrund läuft.

<container_id>

Stellen Sie sich nun vor, unser "Webanwendungs"-Container muss einen Befehl ausführen, der mit der Datenbank interagiert, wie z.B. ein Datenbank-Migrationsskript. Normalerweise, wenn wir Docker Compose verwenden würden, könnten wir einen Befehl auf dem Web-Service ausführen und Docker Compose würde die Netzwerkeinrichtung und Verknüpfung übernehmen.

Mit nur docker run, wenn wir den Webanwendungs-Container starten würden und er versucht, eine Verbindung zu my-database herzustellen, müsste er sich typischerweise im selben Netzwerk befinden.

Lassen Sie uns einen Befehl in einem ubuntu-Container ausführen, der mit demselben Netzwerk verbunden ist, um einen Befehl zu simulieren, der mit der Datenbank interagieren könnte. Wir versuchen einfach, den Datenbank-Container über seinen Namen (my-database) zu pingen.

docker run --network my-app-network ubuntu ping -c 4 my-database

Dieser Befehl wird:

  1. Einen neuen Container aus dem ubuntu-Image erstellen
  2. Ihn mit dem my-app-network verbinden
  3. Den Befehl ping -c 4 my-database im Container ausführen

Da der ubuntu-Container im selben Netzwerk wie der my-database-Container ist, kann er den Namen my-database in die IP-Adresse des Datenbank-Containers auflösen und ihn anpingen.

Sie sollten eine Ausgabe sehen, die die Ping-Anfragen und Antworten zeigt:

PING my-database (172.18.0.2) 56(84) bytes of data.
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.054 ms

--- my-database ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.050/0.053/0.054/0.001 ms

Dies zeigt, dass Sie einen einmaligen Befehl in einem Container ausführen können und dieser mit anderen Containern im selben Netzwerk interagieren kann, ohne den Standard-Service des Containers starten zu müssen (in diesem Fall hat der ubuntu-Container keinen typischen "Service"). Der Schlüssel liegt darin, den Container, der den Befehl ausführt, mit demselben Netzwerk zu verbinden wie die Services, mit denen er interagieren muss.

Abschließend bereinigen wir den laufenden Datenbank-Container und das Netzwerk.

docker stop my-database
my-database
docker rm my-database
my-database
docker network rm my-app-network
my-app-network

Befehl ausführen und Container automatisch entfernen

In diesem Schritt lernen wir, wie man einen Befehl in einem Docker-Container ausführt und den Container automatisch entfernt, sobald der Befehl abgeschlossen ist. Dies ist besonders nützlich für einmalige Aufgaben, Skripte oder Jobs, bei denen der Container nach Abschluss der Ausführung nicht bestehen bleiben muss. Das automatische Entfernen von Containern hilft, Ihr System sauber zu halten und verhindert die Ansammlung gestoppter Container.

Wir werden für diese Demonstration erneut das ubuntu-Image verwenden. Wir führen einen einfachen Befehl aus, wie das Ausgeben einer Nachricht und anschließendes Beenden. Um den Container nach Abschluss des Befehls automatisch zu entfernen, verwenden wir das Flag --rm mit dem docker run-Befehl.

Lassen Sie uns einen Container mit dem --rm-Flag starten und den Befehl echo "Dieser Container wird automatisch entfernt" ausführen.

docker run --rm ubuntu echo "Dieser Container wird automatisch entfernt"

Dieser Befehl wird:

  1. Einen neuen Container aus dem ubuntu-Image erstellen
  2. Den Befehl echo "Dieser Container wird automatisch entfernt" im Container ausführen
  3. Den Container automatisch entfernen, sobald der echo-Befehl abgeschlossen ist

Sie sollten die Ausgabe des echo-Befehls sehen:

Dieser Container wird automatisch entfernt

Nach Abschluss des Befehls wird der Container gestoppt und entfernt. Um zu überprüfen, ob der Container entfernt wurde, können Sie den Befehl docker ps -a verwenden, der alle Container einschließlich der gestoppten auflistet.

docker ps -a

Sie sollten den gerade ausgeführten Container nicht in der Liste sehen. Wenn Sie den Befehl ohne das --rm-Flag ausgeführt hätten, würde der Container in der Ausgabe mit dem Status "Exited" erscheinen.

Lassen Sie uns ein weiteres Beispiel versuchen. Wir führen einen Befehl aus, der mit sleep für einige Sekunden pausiert und dann beendet, wieder mit dem --rm-Flag.

docker run --rm ubuntu sh -c "echo 'Sleep wird gestartet...'; sleep 5; echo 'Sleep beendet.'"

Dieser Befehl verwendet sh -c, um ein einfaches Skript auszuführen, das Nachrichten vor und nach einer 5-sekündigen Pause ausgibt.

Sie werden die erste Nachricht sofort sehen:

Sleep wird gestartet...

Dann, nach etwa 5 Sekunden, sehen Sie die zweite Nachricht:

Sleep beendet.

Sobald das Skript abgeschlossen ist, wird der Container automatisch entfernt. Sie können dies erneut mit docker ps -a überprüfen.

docker ps -a

Der Container, der den Sleep-Befehl ausgeführt hat, sollte nicht in der Containerliste erscheinen.

Die Verwendung des --rm-Flags ist eine gute Praxis für Container, die für eine bestimmte Aufgabe konzipiert sind und dann beendet werden, da es hilft, Speicherplatz zu verwalten und Ihre Containerliste sauber zu halten.

Zusammenfassung

In diesem Lab haben wir gelernt, wie man den docker compose run-Befehl verwendet, um einmalige Aufgaben innerhalb eines Docker Compose-Services auszuführen. Wir begannen damit zu verstehen, wie man den Standardbefehl in der Service-Konfiguration überschreibt, was uns ermöglicht, beliebige Befehle für administrative oder Debugging-Zwecke auszuführen.

Anschließend haben wir untersucht, wie man die Netzwerkverbindung für diese einmaligen Aufgaben verwaltet, insbesondere durch das Freigeben von Service-Ports und manuelles Port-Mapping. Abschließend haben wir gelernt, wie man Abhängigkeiten steuert, indem man einen Befehl ohne Start verknüpfter Services ausführt, und wie man den Container nach Abschluss des Befehls automatisch entfernt, um eine saubere Umgebung zu gewährleisten.