Ist es möglich, eine Shell-Sitzung in einem laufenden Container zu starten (ohne ssh)

341

Ich hatte naiv erwartet, dass dieser Befehl eine Bash-Shell in einem laufenden Container ausführt:

docker run "id of running container" /bin/bash

es sieht so aus, als wäre es nicht möglich, ich bekomme den Fehler:

2013/07/27 20:00:24 Internal server error: 404 trying to fetch remote history for 27d757283842

Also, wenn ich die Bash-Shell in einem laufenden Container ausführen möchte (z. B. zu Diagnosezwecken)

Muss ich einen SSH-Server darin ausführen und mich über ssh anmelden?

Max L.
quelle
1
docker run CONTAINERist geplant in 1.0
kolypto
7
Seit Docker 1.3 sollten Sie wirklich wie in dieser Antwort
Thomasleveil
1
justdocker attach container_name
maxbellec
1
Es sieht so aus, als ob die zweite Antwort heutzutage viel besser ist als die akzeptierte - könnten Sie die Änderung der akzeptierten Antwort überdenken?
Jsbueno

Antworten:

285

EDIT: Jetzt können Sie docker exec -it "id of running container" bash( doc ) verwenden

Zuvor war die Antwort auf diese Frage:

Wenn Sie wirklich müssen und sich in einer Debug-Umgebung befinden, können Sie dies tun: sudo lxc-attach -n <ID> Beachten Sie, dass die ID die vollständige sein muss ( docker ps -notrunc).

Ich empfehle jedoch dringend dagegen.

Hinweis: -notruncist veraltet, wird --no-truncbald ersetzt.

knarren
quelle
1
warum empfehlen Sie dagegen?
Max L.
7
Ich empfehle dagegen, weil 1) es einen sehr aktuellen Kernel erfordert, 2) Sie Dinge außerhalb des Dockers tun, damit Sie es nicht verfolgen können (Protokolle, Anhängen usw.). Außerdem verwendet Docker derzeit möglicherweise lxc, es gibt jedoch keine Garantie dafür, dass dies für immer der Fall ist.
Creack
1
Versuchen Sie, auf 0.7.6 zu aktualisieren. Docker verwendet derzeit noch lxc und lxc-attachsollte einwandfrei funktionieren. Ich habe gerade doppelt geprüft und es funktioniert für mich. (Beachten Sie, dass es mit Kernel vor 3.8 nicht funktioniert).
Knarren
2
Ab 0.9 läuft Docker standardmäßig nicht mehr mit LXC. Sie müssten den Docker Deamon mitdocker -d -e lxc
Kevzettler
2
Max L., Ihr Anwendungsfall kann mit Datenmengen gelöst werden . Nicht getestetes Beispiel: 1) Container mit Nginx-Protokollen im Datenvolumen ausführen : docker run -v /var/log/nginx -name somename imagename command; 2) Führen Sie einen anderen Container aus, um den Inhalt des Datenvolumens anzuzeigen : docker run -volumes-from somename -i -t busybox /bin/sh.
Ciastek
615

Mit Docker 1.3 gibt es einen neuen Befehl docker exec. Auf diese Weise können Sie einen laufenden Docker eingeben:

docker exec -it "id of running container" bash
Michael_Scharf
quelle
2
Das hat bei mir super funktioniert. Sehr hilfreiche Ergänzung zum Docker Run.
Oraserrata
Was ist, wenn ich während der Ausführung eines laufenden Containers Änderungen vorgenommen habe und die Änderungen online wiedergeben möchte? Was sind die Best Practices?
Mediaroot
Sehr hilfreich. Vielen Dank
luongnv89
Verwenden Sie docker ps, um ID der laufenden Instanzen zu erhalten
Myon
Hinweis: Der Container verfügt möglicherweise nicht über bash (»exec:" bash ": ausführbare Datei nicht gefunden«). Verwenden Sie docker inspect <image>diese Option, um zu sehen, welche Shell verfügbar ist. ZB docker exec -it <container id> /bin/shstattdessen laufen .
Pixelbrackets
14

Mach einfach

docker attach container_name

Wie in den Kommentaren erwähnt, aus dem Behälter zu lösen , ohne sie zu stoppen, geben Sie Ctrlpdann Ctrlq.

maxbellec
quelle
5
Vielen Dank!! Es half. Und im Zusammenhang mit der eigentlichen Frage möchte ich etwas hinzufügen. Nach dem Debuggen von unserem Behälter verwenden, docker attach container_nameverwendet ctrl pund ctrl qstatt exit. exitBefehl stoppt den Container, wo als ctrlpund ctrl qnur diesen Container abtrennt und ihn am Laufen hält
Phoenix
10

Da sich die Dinge ändern, wird derzeit die empfohlene Art des Zugriffs auf einen laufenden Container verwendet nsenter.

Weitere Informationen zu diesem Github-Repository finden Sie . Im Allgemeinen können Sie nsenter jedoch folgendermaßen verwenden:

PID=$(docker inspect --format {{.State.Pid}} <container_name_or_ID>)
nsenter --target $PID --mount --uts --ipc --net --pid

oder Sie können den Wrapper verwenden docker-enter:

docker-enter <container_name_or_ID>

Eine nette Erklärung zu diesem Thema finden Sie in Jérôme Petazzonis Blogeintrag: Warum Sie sshd nicht in Ihren Docker-Containern ausführen müssen

Teudimundo
quelle
Leider werden env-Variablen mit diesem Ansatz durcheinander gebracht (wenn Sie die per Link erstellten Variablen überprüfen möchten). Ich schlage vor zu tun source /proc/*/environ.
Tomas Tomecek
8

Als erstes kannst du nicht rennen

docker run "existing container" command

Da dieser Befehl ein Bild und keinen Container erwartet und ohnehin dazu führen würde, dass ein neuer Container erzeugt wird (also nicht der, den Sie sich ansehen wollten).

Ich stimme der Tatsache zu, dass wir uns mit Docker dazu drängen sollten, anders zu denken (also sollten Sie Wege finden, damit Sie sich nicht in den Container einloggen müssen), aber ich finde es trotzdem nützlich und so arbeite ich um es herum.

Ich führe meine Befehle über den Supervisor im DEAMON-Modus aus.

Dann führe ich das aus, was ich nenne. docker_loop.sh Der Inhalt ist so ziemlich das Folgende:

#!/bin/bash
/usr/bin/supervisord
/usr/bin/supervisorctl
while ( true )
    do
    echo "Detach with Ctrl-p Ctrl-q. Dropping to shell"
    sleep 1
    /bin/bash
done

Es ermöglicht Ihnen, eine Verbindung zum Container supervisorctlherzustellen und die Schnittstelle zum Stoppen / Starten / Neustarten und Überprüfen von Protokollen anzuzeigen. Wenn das nicht ausreichen sollte, können Sie Ctrl+Dund Sie werden in eine Shell fallen, die es Ihnen ermöglicht, einen Blick darauf zu werfen, als wäre es ein normales System.

BITTE BEACHTEN SIE AUCH, dass dieses System nicht so sicher ist wie der Behälter ohne Hülle. Führen Sie daher alle erforderlichen Schritte aus, um Ihren Behälter zu sichern.

Alessandro
quelle
5

Behalten Sie diese Pull-Anfrage im Auge: https://github.com/docker/docker/pull/7409

Welches implementiert das bevorstehende docker exec <container_id> <command>Dienstprogramm. Wenn dies verfügbar ist, sollte es möglich sein, z. B. den SSH-Dienst in einem laufenden Container zu starten und zu stoppen.

Dazu gibt es auch Folgendesnsinit : "nsinit bietet eine praktische Möglichkeit, auf eine Shell im Namespace eines laufenden Containers zuzugreifen" , aber es scheint schwierig zu sein, sie zum Laufen zu bringen. https://gist.github.com/ubergarm/ed42ebbea293350c30a6

foz
quelle
docker execgelandet in Docker 1.3, so ist es jetzt möglich, eine neue Shell-Sitzung in einem laufenden Container zu erstellen und daran teilzunehmen
foz
3

Sie können verwenden

docker exec -it <container_name> bash
Antikytheraton
quelle
1

Es gibt tatsächlich eine Möglichkeit, eine Shell im Container zu haben.

Angenommen, Sie /root/run.shstarten den Prozess, den Prozessmanager (Supervisor) oder was auch immer.

Erstellen Sie /root/runme.shmit einigen Gnu-Screen-Tricks:

# Spawn a screen with two tabs
screen -AdmS 'main' /root/run.sh
screen -S 'main' -X screen bash -l
screen -r 'main'

Jetzt haben Sie Ihre Daemons in Tab 0 und eine interaktive Shell in Tab 1. Sie können docker attachjederzeit sehen, was im Container passiert.

Ein weiterer Rat ist, mit allen erforderlichen Tools, einschließlich dieses Bildschirmtricks, ein "Entwicklungspaket" -Bild über dem Produktionsabbild zu erstellen.

kolypto
quelle
1

Hier ist meine Lösung

Teil von DOckerfile:

...
RUN mkdir -p /opt
ADD initd.sh /opt/
RUN chmod +x /opt/initd.sh
ENTRYPOINT ["/opt/initd.sh"]

Teil von "initd.sh"

#!/bin/bash
...
/etc/init.d/gearman-job-server start
/etc/init.d/supervisor start
#very important!!!
/bin/bash

Nachdem das Image erstellt wurde, haben Sie zwei Optionen mit exec und attach:

  1. mit exec (das ich benutze) ausführen:

Docker-Lauf --name $ CONTAINER_NAME -dt $ IMAGE_NAME

dann

docker exec -it $ CONTAINER_NAME / bin / bash

und verwenden

STRG + D zum Abnehmen

  1. mit anhängen ausführen:

Docker-Lauf --name $ CONTAINER_NAME -dit $ IMAGE_NAME

dann

Docker hängen $ CONTAINER_NAME an

und verwenden

STRG + P und STRG + Q zum Lösen

Der Unterschied zwischen den Optionen liegt im Parameter -i

tim
quelle
1

Es gibt zwei Möglichkeiten.

Mit anhängen

$ sudo docker attach 665b4a1e17b6 #by ID

Mit exec

$ sudo docker exec - -t 665b4a1e17b6 #by ID
Gurubelli
quelle
0

Es ist nützlich, beim Ausführen eines Containers einen Namen zuzuweisen. Sie brauchen keine refer container_id.

docker run --name container_name yourimage docker exec -it container_name bash

Matsumoto Kazuya
quelle
0

Holen Sie sich zunächst die Container-ID des gewünschten Containers von

docker ps

Sie werden so etwas bekommen:

CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS                          PORTS                    NAMES
3ac548b6b315        frontend_react-web     "npm run start"     48 seconds ago      Up 47 seconds                   0.0.0.0:3000->3000/tcp   frontend_react-web_1

Kopieren Sie nun diese Container-ID und führen Sie den folgenden Befehl aus:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh

Umesh
quelle
-2

Vielleicht wurden Sie wie ich in die Irre geführt, bei der Entwicklung von Containern in VMs zu denken. Mein Rat: Versuchen Sie es nicht.

Container sind wie jeder andere Prozess. In der Tat möchten Sie sie möglicherweise zu Debugging-Zwecken "anhängen" (denken Sie an / proc // env oder strace -p), aber das ist ein ganz besonderer Fall.

Normalerweise "führen" Sie den Prozess einfach aus. Wenn Sie also die Konfiguration ändern oder die Protokolle lesen möchten, erstellen Sie einfach einen neuen Container und stellen Sie sicher, dass Sie die Protokolle außerhalb des Containers schreiben, indem Sie Verzeichnisse freigeben und in stdout schreiben (damit Docker-Protokolle funktionieren). oder etwas ähnliches.

Zum Debuggen möchten Sie möglicherweise eine Shell und dann Ihren Code starten und dann STRG-p + STRG-q drücken, um die Shell intakt zu lassen. Auf diese Weise können Sie wieder anbringen mit:

docker attach <container_id>

Wenn Sie den Container debuggen möchten, weil er etwas tut, das Sie nicht erwartet haben, versuchen Sie, ihn zu debuggen: /server/596994/how-can-i-debug-a-docker-container -Initialisierung

estani
quelle
Das ist völlig falsch. Die Möglichkeit, den LXC-Namespace, in dem Ihre Anwendung ausgeführt wird, zu überprüfen, ist kein "ganz besonderer Fall", sondern eine häufige / tägliche Aktivität für jeden Entwickler.
Sleepycal
@sleepycal "jeder Entwickler" klingt ein wenig voreingenommen. In jedem Fall verwende ich die Selbstbeobachtung von Prozessen, so dass das Gleiche für Container gilt. Das ist die Idee hinter dem Debuggen. Sie fügen dem Prozess einen Debugger hinzu (der möglicherweise eine CLI hat). Der Gedanke, dass Sie im Container "angemeldet" sind, klingt für mich immer noch irreführend.
Estani
-4

Nein das ist nicht möglich. Verwenden Sie so etwas wie supervisordeinen SSH-Server, wenn dies erforderlich ist. Obwohl ich definitiv die Notwendigkeit in Frage stelle.

Nick Stinemates
quelle