Wie führe ich einen Befehl für einen bereits vorhandenen Docker-Container aus?

492

Ich habe einen Container mit erstellt, -ddamit er nicht interaktiv ist.

docker run -d shykes/pybuilder bin/bash

Ich sehe, dass der Container verlassen hat:

CONTAINER ID        IMAGE                     COMMAND             CREATED             STATUS                      PORTS               NAMES
d6c45e8cc5f0        shykes/pybuilder:latest   "bin/bash"          41 minutes ago      Exited (0) 2 seconds ago                        clever_bardeen

Jetzt möchte ich gelegentlich Befehle auf der Maschine ausführen und beenden. Nur um die Antwort zu bekommen.

Ich habe versucht, die Maschine zu starten. Ich habe versucht, zu befestigen. Ich dachte, ich könnte runmit einem Container anrufen , aber das scheint nicht erlaubt zu sein. Die Verwendung startscheint nur zu laufen und dann schnell zu existieren.

Ich möchte nach dem Beenden wieder in den interaktiven Modus zurückkehren.

Ich habe es versucht:

docker attach d6c45e8cc5f0

Aber ich verstehe:

2014/10/01 22:33:34 You cannot attach to a stopped container, start it first

Aber wenn ich es starte, wird es trotzdem beendet. Fang 22. Ich kann nicht gewinnen.

Johnston
quelle
Woher wussten Sie, dass der Docker-Container verlassen wurde? Welchen Befehl haben Sie ausgeführt?
Thufir
docker container ls -a
Brandon Manchester
Wenn Sie nur das Dateisystem benötigen: Wie starte ich einen gestoppten Docker-Container mit einem anderen Befehl? (Beachten Sie, dass Umgebungsvariablen und andere Dinge im Speicher bereits verloren gehen, wenn der Container gestoppt wird.)
Franklin Yu

Antworten:

548

Im Oktober 2014 führte das Docker-Team den docker execBefehl ein : https://docs.docker.com/engine/reference/commandline/exec/

Jetzt können Sie jeden Befehl in einem laufenden Container ausführen, ohne dessen ID (oder Namen) zu kennen:

docker exec -it <container_id_or_name> echo "Hello from container!"

Beachten Sie, dass der execBefehl nur für bereits ausgeführte Container funktioniert. Wenn der Container derzeit gestoppt ist, müssen Sie ihn zuerst mit dem folgenden Befehl ausführen:

docker run -it -d shykes/pybuilder /bin/bash

Das Wichtigste dabei ist die -dOption, für die steht detached. Dies bedeutet, dass der Befehl, den Sie ursprünglich für container ( /bin/bash) angegeben haben, im Hintergrund ausgeführt wird und der Container nicht sofort gestoppt wird .

Scadge
quelle
120
Dies funktioniert nicht bei einem gestoppten Container, sondern nur bei einem laufenden. Wenn Sie also einen Container haben, der sich wie in der Frage sofort selbst stoppt, funktioniert dies nicht, um etwas anderes zum Laufen zu bringen.
Interferenz
4
@interfect ist richtig und CDR LDN hat eine umfassendere Antwort.
Dr. Jan-Philip Gehrcke
6
@ Jan-PhilipGehrcke Btw dieser Person Benutzername wird von geändert CDR LDNzu cdrevfür die Antwort unten ( stackoverflow.com/a/26181666/149428 ).
Taylor Edmiston
3
Warum vorbei -it?
Iulian Onofrei
4
omg warum ist das so kompliziert? Scheint das Grundlegendste zu sein, was Sie tun müssen. Wir dürfen es nicht so verwenden, wie sie es beabsichtigen.
Sudo
287

Ihr Container wird verlassen wie der Befehl Sie es gab enden wird. Verwenden Sie die folgenden Optionen, um es am Leben zu erhalten:

  • -i Halten Sie STDIN offen, auch wenn es nicht angebracht ist.
  • -t Ordnen Sie eine Pseudo-TTY zu.

Ihr neuer runBefehl lautet also:

docker run -it -d shykes/pybuilder bin/bash

Wenn Sie an einen bereits laufenden Container anhängen möchten:

docker exec -it CONTAINER_ID /bin/bash

In diesen Beispielen /bin/bashwird als Befehl verwendet.

cdrev
quelle
2
Versuchte docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"und gedruckte leere Variable (erwartet 1). Was vermisse ich?
Yellow01
Nach dem Ausführen von 'docker exec -it CONTAINER_ID / bin / bash' wird die Bash korrekt ausgeführt, kann jedoch nicht mit ihr interagieren.
Blaue Wolken
1
Aber wenn ich Docker-Compose benutze, -itist das nicht verfügbar.
Adnanmuttaleb
120

Daher denke ich, dass die Antwort einfacher ist als viele irreführende Antworten oben.

So starten Sie einen vorhandenen Container, der gestoppt ist

docker start <container-name/ID>

So stoppen Sie einen laufenden Container

docker stop <container-name/ID>

Dann melden Sie sich bei der interaktiven Shell eines Containers an

docker exec -it <container-name/ID> bash

So starten Sie einen vorhandenen Container und hängen ihn mit einem Befehl an

docker start -ai <container-name/ID>

Achtung, dies stoppt den Container beim Verlassen. Im Allgemeinen müssen Sie den Container jedoch starten, anbringen und stoppen, nachdem Sie fertig sind.

Peter T.
quelle
Docker hängen <Containername / ID> an, die ausgeführt wird
KunMing Xie
9
@ Peter T. Eigentlich fand ich Ihre Antwort viel prägnanter als die, die andere bereitgestellt haben. Ich verstehe nicht, warum die Leute es vorziehen, eine sehr einfache Frage zu komplizieren. Danke Peter diese Antwort.
Helen Neely
1
Dies setzt voraus , dass Sie beim Erstellen des Dockers dies mit -it stackoverflow.com/questions/45216612/… getan haben. Andernfalls wird es nicht gestartet. Sie müssen also Docker <container-id> und dann Docker ps -l starten und Sie würden sehen, dass es nach dem Start nicht mehr läuft. und dann würde das Anhängen fehlschlagen. Also muss ich auch mit -it kreieren.
Barlop
1
@ Peter Die relevanteste Antwort
Nilanjan Sarkar
1
Dies ist die genaueste Antwort!
Nagendra547
91

Um die Antwort von katrmr zu erweitern, müssen commitSie ein Bild erstellen, wenn der Container gestoppt ist und aufgrund eines Fehlers nicht gestartet werden kann. Dann können Sie Bash im neuen Image starten:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image
Aaron V.
quelle
1
Zu Ihrer Information, ich mache das so oft, dass ich einen Befehl zusammengestellt habe, der aufgerufen wird dshell, um es in einer Vielzahl von Situationen automatisch zu tun - github.com/avirshup/docker-cli-sugar
Aaron V
41

Einige der Antworten hier sind irreführend, da sie Container betreffen, die ausgeführt und nicht gestoppt werden.

Sven Dowideit erklärte im Docker-Forum, dass Container an ihren Prozess gebunden sind (und Docker den Prozess eines gestoppten Containers nicht ändern kann, was anscheinend zumindest auf seine interne Struktur zurückzuführen ist: https://github.com/docker/docker/issues / 1437 ). Grundsätzlich besteht die einzige Option darin, commitden Container auf ein Bild und runeinen anderen Befehl zu setzen.

Siehe https://forums.docker.com/t/run-command-in-stopped-container/343
(Ich glaube, der ENTRYPOINTAnsatz " mit Argumenten" würde auch nicht funktionieren, da Sie das immer noch nicht ändern können Argumente für einen gestoppten Container.)

katrmr
quelle
2
Hinweis: Wenn Sie bin/bashohne -itausführen, ändert sich nichts am Container. Daher ist das Festschreiben nicht unbedingt erforderlich, und CDR LDN gibt die richtige Antwort für die jeweilige Situation des OP. Dennoch commitist die Antwort auf das technische Problem, wie der Containerprozess geändert werden kann.
Katrmr
Der Kommentar von candlerb bei run-command-in-stop-container, der vorschlägt, ein Wegwerfbild mit dem Volume aus dem inaktiven Container zu verwenden, hat für mich funktioniert: docker run --rm --volumes-from CONTAINER -i Busybox tar cO / var / DIR | gzip -c> ~ / mydir_backup.tgz
Aal ghEEz
Dies ist die eigentliche Antwort auf die gestellte Frage. Container sind an ihren Prozess gebunden, sodass der Befehl nicht geändert werden kann.
Cjsimon
21

Ich musste bash -c verwenden, um meinen Befehl auszuführen: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"

velop
quelle
1
-c hat für mich gearbeitet.
Ich
18

Erstellen eines Containers und Senden von Befehlen nacheinander:

docker create --name=my_new_container -it ubuntu
docker start my_new_container
// ps -a says 'Up X seconds'
docker exec my_new_container /path/to/my/command
// ps -a still says 'Up X+Y seconds'
docker exec my_new_container /path/to/another/command
langlauf.io
quelle
Dies ist die gute Antwort auf die Frage. Wenn Sie den Container nach der Erstellung starten und Befehle "docker exec" darin ausführen möchten, müssen Sie ihn mit den Flags "-it" im Befehl "docker create" erstellen.
Joanlofe
8

Dies ist eine kombinierte Antwort, die ich mit der obigen CDR-LDN-Antwort und der hier gefundenen Antwort zusammengestellt habe .

Im folgenden Beispiel wird ein Arch Linux-Container von einem Image aus gestartet und anschließend gitmit dem pacmanTool auf diesem Container installiert :

sudo docker run -it -d archlinux /bin/bash
sudo docker ps -l
sudo docker exec -it [container_ID] script /dev/null -c "pacman -S git --noconfirm"

Das ist alles.

imriss
quelle
5

Wenn Sie versuchen, ein Shell-Skript auszuführen, müssen Sie es als Bash ausführen.

docker exec -it containerid bash -c /path/to/your/script.sh
MrKulli
quelle
4

Leiten Sie einen Befehl an stdin

Muss das entfernen, -tdamit es funktioniert:

echo 'touch myfile' | sudo docker exec -i CONTAINER_NAME bash

Dies kann praktischer sein als manchmal die Verwendung von CLI-Optionen.

Getestet mit:

sudo docker run --name ub16 -it ubuntu:16.04 bash

dann auf einer anderen Shell:

echo 'touch myfile' | sudo docker exec -i ub16 bash

Dann auf der ersten Schale:

ls -l myfile

Getestet auf Docker 1.13.1, Ubuntu 16.04 Host.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
3

Angenommen, das Image verwendet den Standardeinstiegspunkt /bin/sh -c, wird die Ausführung /bin/bashsofort im Daemon-Modus ( -d) beendet. Wenn dieser Container eine interaktive Shell ausführen soll, verwenden Sie -itanstelle von -d. Wenn Sie beliebige Befehle in einem Container ausführen möchten, der normalerweise einen anderen Prozess ausführt, möchten Sie möglicherweise versuchen, nsenteroder nsinit. Weitere Informationen finden Sie unter https://blog.codecentric.de/de/2014/07/enter-docker-container/ .

Andreas Steffan
quelle
3

Leider ist es unmöglich, ENTRYPOINTmit Argumenten zu überschreiben docker run --entrypoint, um dieses Ziel zu erreichen.

Hinweis: Sie können die ENTRYPOINT-Einstellung mit --entrypoint überschreiben, dies kann jedoch nur die Binärdatei auf exec setzen (es wird kein sh -c verwendet).

wieczorek1990
quelle
3

Ich möchte darauf hinweisen, dass die Top-Antwort etwas irreführend ist.

Das Problem bei der Ausführung docker runist, dass jedes Mal ein neuer Container erstellt wird. Es gibt jedoch Fälle, in denen wir alte Container erneut besuchen oder mit neuen Containern keinen Platz beanspruchen möchten.

(Gegeben clever_bardeenist der Name des erstellten Containers ...)

Stellen Sie im Fall von OP sicher, dass das Docker-Image zuerst ausgeführt wird, indem Sie den folgenden Befehl ausführen:

docker start clever_bardeen

Führen Sie dann den Docker-Container mit dem folgenden Befehl aus:

docker exec -it clever_bardeen /bin/bash
Josh
quelle
2

Für Mac:

$ docker exec -it <container-name> sh

Wenn Sie als Root-Benutzer eine Verbindung herstellen möchten:

$ docker exec -u 0 -it <container-name> sh
Lyncean Patel
quelle
1

Einfache Antwort: gleichzeitig starten und anhängen. In diesem Fall tun Sie genau das, wonach Sie gefragt haben.

docker start <CONTAINER_ID/CONTAINER_NAME> && docker attach <CONTAINER_ID/CONTAINER_NAME> 

Stellen Sie sicher, dass Sie sich ändern <CONTAINER_ID/CONTAINER_NAME>

user353305
quelle
1
# docker exec -d container_id command 

Ex:

# docker exec -d xcdefrdtt service jira stop 
Rajesh Gurram
quelle
1

Ich führe einen Windows-Container aus und muss im Docker-Container nach Dateien und Ordnern suchen, die erstellt und kopiert wurden.

Zu diesem Zweck habe ich den folgenden Docker-Einstiegspunktbefehl verwendet, um die Eingabeaufforderung im Container auszuführen oder an den Container anzuhängen.

ENTRYPOINT ["C:\\Windows\\System32\\cmd.exe", "-D", "FOREGROUND"]

Das hat mir geholfen, sowohl an die Eingabeaufforderung an den Container anzuhängen als auch den Container am Leben zu erhalten. :) :)

Jenish Rabadiya
quelle
0

Eine schnelle Möglichkeit, den zuletzt verlassenen Container fortzusetzen und darauf zuzugreifen:

docker start -a -i `docker ps -q -l`
Pierz
quelle
0

Ich benutze normalerweise Folgendes:

    docker exec -it my-container-name bash

kontinuierlich mit einem laufenden Container zu interagieren.

Amin Shojaei
quelle