Die Ausführung von Befehlen innerhalb eines Docker-Containers ist einfacher als Sie denken.

Ein Docker-Container ist eine isolierte Umgebung, die normalerweise eine einzelne Anwendung mit allen erforderlichen Abhängigkeiten enthält. Oft müssen wir einige Befehle innerhalb eines Docker-Containers ausführen. Es gibt mehrere Möglichkeiten, wie wir einen Befehl innerhalb eines Containers ausführen und die gewünschte Ausgabe erhalten können.

Sehen wir uns an, wie wir das machen können.

Interaktive Shell verwenden

Wir können direkt auf die Shell eines Containers zugreifen und unsere Befehle wie mit einem normalen Linux-Terminal ausführen. Um eine interaktive Shell eines gestoppten (nicht laufenden) Containers zu erhalten, können Sie Folgendes verwenden:

$ docker run -it ubuntu bash
root@c520631f652d:/#

Wie Sie sehen können, landen wir direkt in einem neuen Ubuntu-Container, in dem wir unsere Befehle ausführen können. Wenn bereits ein Container läuft, können Sie den Befehl exec wie unten beschrieben verwenden.

Lassen Sie uns zunächst die Container-ID herausfinden.

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2d969adde7a nginx "/docker-entrypoint...." vor 2 Stunden Up 2 Stunden 127.0.0.1:80->80/tcp nginx
0960560bc24b mariadb "docker-entrypoint.s..." vor 2 Stunden Up 2 Stunden 127.0.0.1:3306->3306/tcp mariadb

Und dann gelangen Sie in die Container-ID c2d969adde7a

$ docker exec -it c2d969adde7a bash 
root@c2d969adde7a:/#

In der obigen Ausgabe können Sie sehen, dass wir eine Bash-Sitzung des nginx-Containers gestartet haben, der sich in einem laufenden Zustand befindet. Hier können wir jeden unterstützten Befehl ausführen und die Ausgabe erhalten.

Hinweis: Möglicherweise verfügt Ihr Container nicht über Bash, dann können Sie sh verwenden.

Beispiel:

docker exec -it c2d969adde7a sh

Direkte Ausgabe

Oft benötigen wir nur die Ausgabe von einem oder zwei Befehlen und brauchen keine vollständige interaktive Sitzung für unsere Aufgabe. Sie können den gewünschten Befehl innerhalb eines Containers ausführen und seine Ausgabe direkt abrufen, ohne eine neue Shell-Sitzung zu öffnen, indem Sie den Befehl exec ohne das Flag -it verwenden. Die Syntax würde lauten:

$ docker exec <Container-Id oder -Name> <Befehl>

Hier ist ein Beispiel:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2d969adde7a nginx "/docker-entrypoint...." vor 2 Stunden Up 2 Stunden 127.0.0.1:80->80/tcp nginx
0960560bc24b mariadb "docker-entrypoint.s..." vor 2 Stunden Up 2 Stunden 127.0.0.1:3306->3306/tcp mariadb

$ docker exec 0960560bc24b ps -ef | grep mysql
mysql 1 0 0 13:35 ?        00:00:02 mysqld
$

Wir haben den Befehl ps -ef | grep mysql innerhalb des laufenden MariaDB-Containers ausgeführt und die Ausgabe direkt erhalten.

Dockerfile Weg

Dies ist nicht die exakte Art und Weise, wie Sie Befehle innerhalb eines Docker-Containers ausführen können, obwohl dies in Entwicklungssituationen oder bei der anfänglichen Fehlersuche bei der Bereitstellung usw. hilfreich sein kann. Wir können den Befehl RUN innerhalb einer Dockerdatei verwenden. Hier ist unser Beispiel-Dockerfile:

FROM nginx:latest
RUN nginx -V

Es zieht einfach das neueste Nginx-Image aus der Registry und führt dann den Befehl nginx -V aus, um die Nginx-Version anzuzeigen, wenn Sie das Image erstellen.

$ docker build -t nginx-test .
Senden des Build-Kontextes an den Docker-Daemon 2.048kB
Schritt 1/2 : FROM nginx:latest
 --->
 7ce4f91ef623
Schritt 2/2 : RUN nginx -V
 --->
 Läuft in 43918bbbeaa5
nginx Version: nginx/1.19.9
gebaut mit gcc 8.3.0 (Debian 8.3.0-6)
gebaut mit OpenSSL 1.1.1d 10 Sep 2019
TLS SNI Unterstützung aktiviert
configure-Argumente: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --mit-http_gzip_static_module --mit-http_mp4_module --mit-http_random_index_module --mit-http_realip_module --mit-http_secure_link_module --mit-http_slice_module --mit-http_ssl_module --mit-http_stub_status_module --mit-http_sub_module --mit-http_v2_module --mit-mail --mit-mail_ssl_module --mit-stream --mit-stream_realip_module --mit-stream_ssl_module --mit-stream_ssl_preread_module --mit-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.9/debian/debuild-base/nginx-1.19.9=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'
Entfernen des Zwischencontainers 43918bbbeaa5
 --->
 d682277f2e50
Erfolgreich gebaut d682277f2e50
Erfolgreich getaggt nginx-test:latest
$

Beachten Sie die Ausgabe des Befehls RUN im obigen Ausschnitt. Der obige Ausschnitt wird nur beim ersten Build angezeigt. Bei nachfolgenden Builds wird die Ausgabe des RUN-Befehls nicht mehr wiederholt. Als Abhilfe können Sie das --no-cache Flag verwenden:

$ docker build -t nginx-test . --no-cache

Die letzte Methode ist nicht der beste Weg, kann aber manchmal für die Fehlersuche usw. hilfreich sein.

Zusammenfassung

Die Ausführung eines Befehls innerhalb eines Docker-Containers ist einfach und es gibt einige Methoden, um dies zu tun. Es ist eine regelmäßige Aufgabe eines Docker-Administrators, daher ist es nützlich, diese Befehle zu kennen.

More on Docker