Est-il possible de démarrer une session shell dans un conteneur en cours d'exécution (sans ssh)

341

Je m'attendais naïvement à ce que cette commande exécute un shell bash dans un conteneur en cours d'exécution:

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

on dirait que ce n'est pas possible, j'obtiens l'erreur:

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

Donc, si je veux exécuter le shell bash dans un conteneur en cours d'exécution (par exemple à des fins de diagnostic)

dois-je y exécuter un serveur SSH et me connecter via ssh?

Max L.
la source
1
docker run CONTAINERest prévu en 1.0
kolypto
7
Depuis docker 1.3, vous devriez vraiment faire comme décrit dans cette réponse
Thomasleveil
1
justedocker attach container_name
maxbellec
1
Il semble que la deuxième réponse est bien meilleure de nos jours que celle acceptée - pourriez-vous reconsidérer la modification de la réponse acceptée?
jsbueno

Réponses:

285

EDIT: Maintenant, vous pouvez utiliser docker exec -it "id of running container" bash( doc )

Auparavant, la réponse à cette question était:

Si vous le devez vraiment et que vous êtes dans un environnement de débogage, vous pouvez le faire: sudo lxc-attach -n <ID> Notez que l'id doit être le plein ( docker ps -notrunc).

Cependant, je déconseille fortement cela.

avis: -notruncest obsolète, il sera remplacé par --no-truncbientôt.

creack
la source
1
pourquoi le déconseillez-vous?
Max L.
7
Je le déconseille car 1) il nécessite un noyau très récent, 2) vous faites des choses en dehors de docker donc vous ne pourrez pas le suivre (logs, attach, etc.). En outre, docker peut utiliser lxc en ce moment, mais il n'y a aucune garantie qu'il le fera pour toujours.
creack
1
Essayez la mise à jour vers 0.7.6. Docker utilise toujours lxc en ce moment et lxc-attachdevrait très bien fonctionner. J'ai juste vérifié deux fois et cela fonctionne pour moi. (Notez qu'il ne fonctionnera pas avec le noyau antérieur à la version 3.8).
creack
2
à partir de 0.9 docker ne fonctionne plus avec LXC par défaut. Vous devrez lancer le docker deamon avecdocker -d -e lxc
kevzettler
2
Max L., votre cas d'utilisation peut être résolu avec des volumes de données . Exemple non testé: 1) contenant exécuté avec les journaux nginx en volume de données: docker run -v /var/log/nginx -name somename imagename command; 2) exécuter un autre récipient pour afficher le contenu du volume de données: docker run -volumes-from somename -i -t busybox /bin/sh.
ciastek
615

Avec docker 1.3, il y a une nouvelle commande docker exec. Cela vous permet d'entrer un docker en cours d'exécution:

docker exec -it "id of running container" bash
Michael_Scharf
la source
2
Cela a très bien fonctionné pour moi. Complément très utile à Docker Run.
oraserrata
Que se passe-t-il si j'ai apporté des modifications lors de l'exécution d'un conteneur en cours d'exécution et que je voulais refléter les modifications en ligne? quelles sont les meilleures pratiques?
mediaroot
Très utile. Merci
luongnv89
utiliser docker pspour obtenir l'identifiant des instances en cours d'exécution
muon
Remarque: Le conteneur peut ne pas avoir bash (»exec:" bash ": fichier exécutable introuvable«). Utilisez docker inspect <image>pour voir quel shell est disponible. Par exemple, courez à la docker exec -it <container id> /bin/shplace.
pixelbrackets
14

Fais juste

docker attach container_name

Comme mentionné dans les commentaires, pour vous détacher du conteneur sans l'arrêter, tapez Ctrlpalors Ctrlq.

maxbellec
la source
5
Merci!! Ça m'a aidé. Et dans le contexte de la question réelle, je voudrais ajouter quelque chose. Après avoir débogué notre conteneur en utilisant, docker attach container_nameutilisez ctrl pet ctrl qau lieu de exit. exitcommande arrête le conteneur, où au fur ctrlpet ctrl qà mesure détache ce conteneur et le maintient en marche
phoenix
10

Étant donné que les choses changent, à l'heure actuelle, la méthode recommandée pour accéder à un conteneur en cours d'exécution est d'utiliser nsenter.

Vous pouvez trouver plus d'informations à ce sujet référentiel github . Mais en général, vous pouvez utiliser nsenter comme ceci:

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

ou vous pouvez utiliser le wrapper docker-enter:

docker-enter <container_name_or_ID>

Une belle explication sur le sujet peut être trouvée sur l'entrée de blog de Jérôme Petazzoni: Pourquoi vous n'avez pas besoin d'exécuter sshd dans vos conteneurs Docker

Teudimundo
la source
malheureusement, les variables env sont gâchées en utilisant cette approche (si vous souhaitez vérifier les variables créées par lien). Je suggère de faire source /proc/*/environ.
Tomas Tomecek
8

La première chose que vous ne pouvez pas exécuter

docker run "existing container" command

Parce que cette commande attend une image et non un conteneur et qu'elle entraînerait de toute façon la création d'un nouveau conteneur (donc pas celui que vous vouliez regarder)

Je suis d'accord avec le fait qu'avec Docker, nous devons nous pousser à penser différemment (donc vous devriez trouver des moyens pour que vous n'ayez pas besoin de vous connecter au conteneur), mais je le trouve toujours utile et c'est ainsi que je travaille autour de.

J'exécute mes commandes via le superviseur en mode DEAMON.

Ensuite, j'exécute ce que j'appelle docker_loop.sh Le contenu est à peu près ceci:

#!/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

Ce qu'il fait, c'est qu'il vous permet de «vous attacher» au conteneur et d'être présenté avec l' supervisorctlinterface pour arrêter / démarrer / redémarrer et vérifier les journaux. Si cela ne suffit pas, vous pouvez Ctrl+Det vous tomberez dans un shell qui vous permettra d'avoir un aperçu comme si c'était un système normal.

VEUILLEZ ÉGALEMENT TENIR COMPTE du fait que ce système n'est pas aussi sûr que d'avoir le conteneur sans coque, alors prenez toutes les mesures nécessaires pour sécuriser votre conteneur.

Alessandro
la source
5

Gardez un œil sur cette demande de tirage: https://github.com/docker/docker/pull/7409

Qui implémente l' docker exec <container_id> <command>utilitaire à venir . Lorsque cela est disponible, il devrait être possible, par exemple, de démarrer et d'arrêter le service ssh à l'intérieur d'un conteneur en cours d'exécution.

Il faut également nsinitprocéder comme suit : "nsinit fournit un moyen pratique d'accéder à un shell à l'intérieur de l'espace de noms d'un conteneur en cours d'exécution" , mais il semble difficile à exécuter. https://gist.github.com/ubergarm/ed42ebbea293350c30a6

foz
la source
docker execatterri dans Docker 1.3, il est donc désormais possible de créer et de rejoindre une nouvelle session shell dans un conteneur en cours d'exécution
foz
3

Vous pouvez utiliser

docker exec -it <container_name> bash
anticythère
la source
1

Il y a en fait un moyen d'avoir un shell dans le conteneur.

Supposons que votre /root/run.shlance le processus, le gestionnaire de processus (superviseur) ou autre.

Créez /root/runme.shavec quelques astuces gnu-screen:

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

Maintenant, vous avez vos démons dans l'onglet 0 et un shell interactif dans l'onglet 1. docker attachà tout moment pour voir ce qui se passe à l'intérieur du conteneur.

Un autre conseil est de créer une image "bundle de développement" au-dessus de l'image de production avec tous les outils nécessaires, y compris cette astuce d'écran.

kolypto
la source
1

voici ma solution

partie de DOckerfile:

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

partie de "initd.sh"

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

une fois l'image créée, vous avez deux options en utilisant exec et attach:

  1. avec exec (que j'utilise), lancez:

docker run --name $ CONTAINER_NAME -dt $ IMAGE_NAME

puis

docker exec -it $ CONTAINER_NAME / bin / bash

et utilise

CTRL + D à détacher

  1. avec attacher, exécuter:

docker run --name $ CONTAINER_NAME -dit $ IMAGE_NAME

puis

docker attacher $ CONTAINER_NAME

et utilise

CTRL + P et CTRL + Q à détacher

la différence entre les options est dans le paramètre -i

Tim
la source
1

Il y a deux façons.

Avec attache

$ sudo docker attach 665b4a1e17b6 #by ID

Avec exec

$ sudo docker exec - -t 665b4a1e17b6 #by ID
gurubelli
la source
0

Il est utile d'attribuer un nom lors de l'exécution du conteneur. Vous n'avez pas besoin de référencer container_id.

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

Matsumoto Kazuya
la source
0

tout d'abord, obtenez l'ID de conteneur du conteneur souhaité en

docker ps

vous obtiendrez quelque chose comme ceci:

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

Copiez maintenant cet ID de conteneur et exécutez la commande suivante:

docker exec -it container_id sh

docker exec -it 3ac548b6b315 sh

Umesh
la source
-2

Peut-être que vous avez été induit en erreur comme moi en pensant en termes de VM lors du développement de conteneurs. Mon conseil: essayez de ne pas le faire.

Les conteneurs sont comme tout autre processus. En effet, vous voudrez peut-être les "attacher" à des fins de débogage (pensez à / proc // env ou strace -p) mais c'est un cas très spécial.

Normalement, vous "exécutez" simplement le processus, donc si vous souhaitez modifier la configuration ou lire les journaux, créez simplement un nouveau conteneur et assurez-vous d'écrire les journaux en dehors de celui-ci en partageant les répertoires, en écrivant sur stdout (pour que les journaux de docker fonctionnent) ou quelque chose comme ça.

À des fins de débogage, vous souhaiterez peut-être démarrer un shell, puis votre code, puis appuyez sur CTRL-p + CTRL-q pour laisser le shell intact. De cette façon, vous pouvez le rattacher en utilisant:

docker attach <container_id>

Si vous souhaitez déboguer le conteneur parce qu'il fait quelque chose que vous ne pensiez pas qu'il fasse, essayez de le déboguer: /server/596994/how-can-i-debug-a-docker-container -initialisation

estani
la source
C'est complètement faux. Pouvoir introspecter l'espace de noms LXC dans lequel votre application s'exécute n'est pas un "cas très spécial", c'est une activité courante / quotidienne pour tout développeur.
sleepycal
@sleepycal "tout développeur" semble un peu biaisé. Dans tous les cas, j'utilise l'introspection des processus donc la même chose s'applique aux conteneurs. C'est l'idée derrière le débogage. Vous attachez un débogueur au processus (qui peut avoir un cli). Penser que vous "êtes" connecté au conteneur me semble toujours trompeur.
estani
-4

Non, ce n'est pas possible. Utilisez quelque chose comme supervisordpour obtenir un serveur ssh si nécessaire. Bien que je remette définitivement en question la nécessité.

Nick Stinemates
la source