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.


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 .


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.


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é.


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

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é.)


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"


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

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.


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

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.


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.


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é).


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

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

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>


1
# docker exec -d container_id command 

Ex:

# docker exec -d xcdefrdtt service jira stop 

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. :)


0

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

docker start -a -i `docker ps -q -l`

0

J'utilise habituellement ceci:

    docker exec -it my-container-name bash

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.