Comment exécuter une commande sur un conteneur Docker déjà existant?

495

J'ai créé un conteneur avec -ddonc ce n'est pas interactif.

docker run -d shykes/pybuilder bin/bash

Je vois que le conteneur est sorti:

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

Maintenant, je voudrais exécuter des commandes occasionnelles sur la machine et quitter. Juste pour obtenir la réponse.

J'ai essayé de démarrer la machine. J'ai essayé d'attacher. Je pensais pouvoir appeler runavec un conteneur, mais cela ne semble pas être autorisé. L'utilisation startsemble juste fonctionner et puis exister rapidement.

Je voudrais revenir en mode interactif après avoir quitté.

J'ai essayé:

docker attach d6c45e8cc5f0

Mais je reçois:

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

Mais si je le démarre, il sort quand même. Catch 22. Je ne peux pas gagner.

Johnston
la source
comment saviez-vous que le conteneur docker était sorti? quelle commande avez-vous exécutée?
Thufir
docker container ls -a
Brandon Manchester
Si vous avez juste besoin du système de fichiers: comment démarrer un conteneur Docker arrêté avec une commande différente? (Notez que les variables d'environnement et autres choses en mémoire sont déjà perdues lorsque le conteneur s'est arrêté.)
Franklin Yu

Réponses:

550

En octobre 2014, l' équipe Docker a introduit la docker execcommande : https://docs.docker.com/engine/reference/commandline/exec/

Alors maintenant, vous pouvez exécuter n'importe quelle commande dans un conteneur en cours d'exécution en connaissant simplement son ID (ou son nom):

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

Notez que la execcommande ne fonctionne que sur un conteneur déjà en cours d'exécution. Si le conteneur est actuellement arrêté, vous devez d'abord l'exécuter avec la commande suivante:

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

La chose la plus importante ici est l' -doption, qui représente detached. Cela signifie que la commande que vous avez initialement fournie au conteneur ( /bin/bash) sera exécutée en arrière-plan et que le conteneur ne s'arrêtera pas immédiatement .

Scadge
la source
120
Cela ne fonctionne pas sur un conteneur arrêté, uniquement sur un conteneur en cours d'exécution. Donc, si vous avez un conteneur qui s'arrête immédiatement, comme dans la question, cela ne fonctionnera pas réellement pour faire fonctionner autre chose à l'intérieur.
interfect
4
@interfect a raison, et CDR LDN a une réponse plus complète.
Dr Jan-Philip Gehrcke
6
@ Jan-PhilipGehrcke BTW nom d'utilisateur de cette personne a changé de CDR LDNà cdrevla réponse ci - dessous ( stackoverflow.com/a/26181666/149428 ).
Taylor Edmiston
3
Pourquoi passer -it?
Iulian Onofrei
4
omg pourquoi est-ce si compliqué? On dirait que la chose la plus élémentaire que vous devez faire. Nous ne devons pas l'utiliser comme ils l'entendent.
sudo
287

Votre conteneur sortie que la commande vous lui avez donné prendra fin. Utilisez les options suivantes pour le maintenir en ligne:

  • -i Gardez STDIN ouvert même s'il n'est pas attaché.
  • -t Attribuez un pseudo-ATS.

Votre nouvelle runcommande est donc:

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

Si vous souhaitez attacher à un conteneur déjà en cours d'exécution:

docker exec -it CONTAINER_ID /bin/bash

Dans ces exemples, /bin/bashla commande est utilisée.

cdrev
la source
2
docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"Variable vide testée et imprimée (attendue 1). Qu'est-ce que je rate?
yellow01
après avoir exécuté 'docker exec -it CONTAINER_ID / bin / bash', il va correctement à bash mais ne peut pas interagir avec lui.
Blue Clouds
1
Mais si j'utilise docker-compose, le -itn'est pas disponible.
adnanmuttaleb
120

Je pense donc que la réponse est plus simple que de nombreuses réponses trompeuses ci-dessus.

Pour démarrer un conteneur existant qui est arrêté

docker start <container-name/ID>

Pour arrêter un conteneur en cours d'exécution

docker stop <container-name/ID>

Ensuite, pour vous connecter au shell interactif d'un conteneur

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

Pour démarrer un conteneur existant et s'y attacher en une seule commande

docker start -ai <container-name/ID>

Attention, cela arrêtera le conteneur en sortie. Mais en général, vous devez démarrer le conteneur, l'attacher et l'arrêter une fois que vous avez terminé.

Peter T.
la source
docker attach <nom-conteneur / ID> en cours d'exécution
KunMing Xie
9
@Peter T. En fait, j'ai trouvé votre réponse beaucoup plus concise que ce que d'autres ont fourni. Je ne comprends pas pourquoi les gens préfèrent compliquer une question très simple. Merci Peter cette réponse.
Helen Neely
1
cela nécessite que lorsque vous avez créé Docker, vous l'avez fait avec -it stackoverflow.com/questions/45216612/… sinon cela ne démarrera pas. et vous verriez que ce n'est pas en place après le début. puis l'attachement échouerait. Il faut donc créer avec -it aussi.
barlop
1
@Peter La réponse la plus pertinente
Nilanjan Sarkar
1
Ceci est la réponse la plus précise!
nagendra547
91

Pour développer la réponse de katrmr, si le conteneur est arrêté et ne peut pas être démarré en raison d'une erreur, vous en aurez besoin commitdans une image. Ensuite, vous pouvez lancer bash dans la nouvelle image:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image
Aaron V
la source
1
Pour info, je le fais tellement que j'ai mis en place une commande appelée dshellpour le faire automatiquement dans une variété de situations - github.com/avirshup/docker-cli-sugar
Aaron V
41

Certaines des réponses ici sont trompeuses car elles concernent des conteneurs en cours d'exécution et non arrêtés.

Sven Dowideit a expliqué sur le forum Docker que les conteneurs sont liés à leur processus (et Docker ne peut pas changer le processus d'un conteneur arrêté, apparemment en raison au moins de sa structure interne: https://github.com/docker/docker/issues / 1437 ). Donc, fondamentalement, la seule option est de commitcréer un conteneur vers une image et runavec une commande différente.

Voir https://forums.docker.com/t/run-command-in-stopped-container/343
(je pense que l' ENTRYPOINTapproche " avec arguments" ne fonctionnerait pas non plus, car vous ne pourriez toujours pas modifier la arguments à un conteneur arrêté.)

katrmr
la source
2
Remarque: courir bin/bashsans -itne changerait rien dans le conteneur, donc le commettre n'est pas vraiment nécessaire et CDR LDN donne la bonne réponse à la situation particulière de l'OP. Pourtant, commitc'est la réponse au problème technique de la façon de changer le processus de conteneur.
katrmr
Le commentaire de candlerb sur run-command-in-stop-container suggérant d'utiliser une image jetable avec le volume du conteneur inactif a fonctionné pour moi: docker run --rm --volumes-from CONTAINER -i busybox tar cO / var / DIR | gzip -c> ~ / mydir_backup.tgz
anguille ghEEz
Ceci est la vraie réponse à la question posée. Les conteneurs sont liés à leur processus, la commande ne peut donc pas être modifiée.
cjsimon
21

J'ai dû utiliser bash -c pour exécuter ma commande: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"

velop
la source
1
-c a fonctionné pour moi. me demande pourquoi bash seul ne fonctionnerait pas (ne reçoit pas d'invite)
André Werlang
18

Créer un conteneur et lui envoyer des commandes une par une:

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
la source
C'est la bonne réponse à la question. Si vous voulez démarrer le conteneur après sa création et pouvoir y "docker exec", vous devez le créer avec les drapeaux "-it" dans la commande docker create.
joanlofe
8

Il s'agit d'une réponse combinée que j'ai inventée en utilisant la réponse CDR LDN ci-dessus et la réponse que j'ai trouvée ici .

L'exemple suivant démarre un conteneur Arch Linux à partir d'une image, puis installe gitsur ce conteneur à l'aide de l' pacmanoutil:

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"

C'est tout.

imriss
la source
5

Si vous essayez d'exécuter un script shell, vous devez l'exécuter en tant que bash.

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

Envoyer une commande à stdin

Doit supprimer le -tpour que cela fonctionne:

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

Cela peut être plus pratique que l'utilisation des options CLI parfois.

Testé avec:

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

puis sur un autre shell:

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

Puis sur le premier shell:

ls -l myfile

Testé sur Docker 1.13.1, hôte Ubuntu 16.04.

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

En supposant que l'image utilise le point d'entrée par défaut /bin/sh -c, l'exécution se /bin/bashterminera immédiatement en mode démon ( -d). Si vous souhaitez que ce conteneur exécute un shell interactif, utilisez -itplutôt que -d. Si vous souhaitez exécuter des commandes arbitraires dans un conteneur exécutant généralement un autre processus, vous pouvez essayer nsenterou nsinit. Jetez un œil à https://blog.codecentric.de/en/2014/07/enter-docker-container/ pour les détails.

Andreas Steffan
la source
3

Malheureusement, il est impossible de passer outre ENTRYPOINTaux arguments avec docker run --entrypointpour atteindre cet objectif.

Remarque: vous pouvez remplacer le paramètre ENTRYPOINT à l'aide de --entrypoint, mais cela ne peut que définir le binaire sur exec (aucun sh -c ne sera utilisé).

wieczorek1990
la source
3

Je voudrais noter que la première réponse est un peu trompeuse.

Le problème avec l'exécution docker runest qu'un nouveau conteneur est créé à chaque fois. Cependant, il y a des cas où nous aimerions revoir de vieux conteneurs ou ne pas prendre de place avec de nouveaux conteneurs.

(Étant donné clever_bardeenle nom du conteneur créé ...)

Dans le cas d'OP, assurez-vous que l'image docker est d'abord exécutée en exécutant la commande suivante:

docker start clever_bardeen

Ensuite, exécutez le conteneur Docker à l'aide de la commande suivante:

docker exec -it clever_bardeen /bin/bash
Josh
la source
2

Pour Mac:

$ docker exec -it <container-name> sh

si vous souhaitez vous connecter en tant qu'utilisateur root:

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

Réponse simple: démarrez et attachez en même temps. Dans ce cas, vous faites exactement ce que vous avez demandé.

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

assurez-vous de changer <CONTAINER_ID/CONTAINER_NAME>

user353305
la source
1
# docker exec -d container_id command 

Ex:

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

J'exécute le conteneur Windows et je dois regarder à l'intérieur du conteneur Docker pour les fichiers et le dossier créés et copiés.

Pour ce faire, j'ai utilisé la commande docker entrypoint suivante pour obtenir l'invite de commande en cours d'exécution à l'intérieur du conteneur ou l'attacher au conteneur.

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

Cela m'a aidé à la fois à l'invite de commande à attacher au conteneur et à garder le conteneur en direct. :)

Jenish Rabadiya
la source
0

Un moyen rapide de reprendre et d'accéder au dernier conteneur quitté:

docker start -a -i `docker ps -q -l`
Pierz
la source
0

J'utilise habituellement ceci:

    docker exec -it my-container-name bash

pour interagir en permanence avec un conteneur en cours d'exécution.

Amin Shojaei
la source