¿Cómo ejecuto un comando en un contenedor Docker ya existente?

495

Creé un contenedor con -dlo que no es interactivo.

docker run -d shykes/pybuilder bin/bash

Veo que el contenedor ha salido:

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

Ahora me gustaría ejecutar comandos ocasionales en la máquina y salir. Solo para obtener la respuesta.

Traté de encender la máquina. Traté de adjuntar. Pensé que podía llamar runcon un contenedor, pero eso no parece estar permitido. El uso startsimplemente parece ejecutarse y luego existir rápidamente.

Me gustaría volver al modo interactivo después de salir.

Lo intenté:

docker attach d6c45e8cc5f0

Pero me sale:

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

Pero si lo comienzo, sale de todos modos. Captura 22. No puedo ganar.

Johnston
fuente
¿Cómo sabías que el contenedor acoplable había salido? ¿Qué comando ejecutaste?
Thufir
docker container ls -a
Brandon Manchester
Si solo necesita el sistema de archivos: ¿Cómo iniciar un contenedor Docker detenido con un comando diferente? (Tenga en cuenta que las variables de entorno y otras cosas en la memoria ya se pierden cuando el contenedor se detuvo.)
Franklin Yu

Respuestas:

550

En octubre de 2014, el equipo de Docker introdujo el docker execcomando : https://docs.docker.com/engine/reference/commandline/exec/

Entonces, ahora puede ejecutar cualquier comando en un contenedor en ejecución con solo conocer su ID (o nombre):

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

Tenga en cuenta que el execcomando solo funciona en el contenedor que ya se está ejecutando. Si el contenedor está actualmente detenido, primero debe ejecutarlo con el siguiente comando:

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

Lo más importante aquí es la -dopción, que significa detached. Significa que el comando que proporcionó inicialmente al contenedor ( /bin/bash) se ejecutará en segundo plano y el contenedor no se detendrá de inmediato .

Scadge
fuente
120
Esto no funciona en un contenedor detenido, solo en uno en ejecución. Entonces, si tiene un contenedor que se detiene inmediatamente, como en la pregunta, en realidad no funcionará para que algo más se ejecute dentro de él.
interfecto
44
@interfect es correcto, y CDR LDN tiene una respuesta más completa.
Dr. Jan-Philip Gehrcke
66
@ Jan-PhilipGehrcke Por cierto, el nombre de usuario de esta persona ha cambiado de CDR LDNa cdrevpara la respuesta a continuación ( stackoverflow.com/a/26181666/149428 ).
Taylor Edmiston
3
¿Por qué pasar -it?
Iulian Onofrei
44
Dios mío, ¿por qué es tan complicado? Parece lo más básico que necesitarías hacer. No debemos usarlo como pretenden.
sudo
287

Su contenedor salir como el comando que diste va a terminar. Use las siguientes opciones para mantenerlo vivo:

  • -i Mantenga STDIN abierto incluso si no está conectado.
  • -t Asignar un pseudo-TTY.

Entonces su nuevo runcomando es:

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

Si desea adjuntar a un contenedor que ya se está ejecutando:

docker exec -it CONTAINER_ID /bin/bash

En estos ejemplos /bin/bashse utiliza como comando.

cdrev
fuente
2
Probado docker exec -it CONTAINER_ID /bin/bash -c "export VAR=1 && echo $VAR"e impreso variable vacía (esperado 1). ¿Qué me estoy perdiendo?
yellow01
después de ejecutar 'docker exec -it CONTAINER_ID / bin / bash', va al bash correctamente pero no puede interactuar con él.
Nubes azules
1
Pero si estoy usando docker-compose, -itno está disponible.
adnanmuttaleb
120

Así que creo que la respuesta es más simple que muchas respuestas engañosas anteriores.

Para iniciar un contenedor existente que se detiene

docker start <container-name/ID>

Para detener un contenedor en funcionamiento

docker stop <container-name/ID>

Luego, para iniciar sesión en el shell interactivo de un contenedor

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

Para iniciar un contenedor existente y adjuntarlo en un comando

docker start -ai <container-name/ID>

Cuidado, esto detendrá el contenedor a la salida. Pero en general, debe iniciar el contenedor, adjuntarlo y detenerlo una vez que haya terminado.

Peter T.
fuente
docker attach <nombre-contenedor / ID> que se está ejecutando
KunMing Xie
99
@Peter T. En realidad, su respuesta me pareció mucho más concisa que la que otros han proporcionado. No entiendo por qué la gente prefiere complicar una pregunta muy simple. Gracias Peter esta respuesta.
Helen Neely
1
esto requiere que cuando creó Docker, lo haya hecho con -it stackoverflow.com/questions/45216612/… de lo contrario no comenzará ... así que haría docker start <container-id> y luego docker ps -l y verías que no está funcionando después del comienzo. y luego el archivo adjunto fallaría. Así que tengo que crear con -it también.
barlop
1
@Peter La respuesta más relevante
Nilanjan Sarkar
1
¡Esta es la respuesta más precisa!
nagendra547
91

Para ampliar la respuesta de katrmr, si el contenedor se detiene y no se puede iniciar debido a un error, deberá commithacerlo en una imagen. Luego puede iniciar bash en la nueva imagen:

docker commit [CONTAINER_ID] temporary_image
docker run --entrypoint=bash -it temporary_image
Aaron V
fuente
1
FYI, hago esto tanto que he creado un comando llamado dshellpara hacerlo automáticamente en una variedad de situaciones: github.com/avirshup/docker-cli-sugar
Aaron V
41

Algunas de las respuestas aquí son engañosas porque se refieren a contenedores que se ejecutan, no se detienen.

Sven Dowideit explicó en el foro de Docker que los contenedores están vinculados a su proceso (y Docker no puede cambiar el proceso de un contenedor detenido, aparentemente debido al menos a su estructura interna: https://github.com/docker/docker/issues / 1437 ). Entonces, básicamente la única opción es commitel contenedor a una imagen y runcon un comando diferente.

Consulte https://forums.docker.com/t/run-command-in-stopped-container/343
(creo que el ENTRYPOINTenfoque " con argumentos" tampoco funcionaría, ya que aún no podría cambiar el argumentos a un contenedor detenido.)

katrmr
fuente
2
Aviso: ejecutar bin/bashsin -itno cambiaría nada en el contenedor, por lo que comprometerse no es realmente necesario y CDR LDN da la respuesta correcta para la situación particular del OP. Aún así, commites la respuesta al problema técnico de cómo cambiar el proceso del contenedor.
katrmr
El comentario de candlerb en run-command-in-stop-container sugiriendo usar una imagen descartable con el volumen del contenedor inactivo funcionó para mí: docker run --rm --volumes-from CONTAINER -i busybox tar cO / var / DIR | gzip -c> ~ / mydir_backup.tgz
anguila ghEEz
Esta es la respuesta real a la pregunta formulada. Los contenedores están vinculados a su proceso, por lo que el comando no se puede cambiar.
cjsimon
21

Tuve que usar bash -c para ejecutar mi comando: docker exec -it CONTAINER_ID bash -c "mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql"

velop
fuente
1
-c funcionó para mí. fiesta de extrañar por qué sí sola no funciona (no obtener una pronta)
André Werlang
18

Creando un contenedor y enviándole comandos, uno por uno:

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
fuente
Esta es la buena respuesta a la pregunta. Si desea iniciar el contenedor después de la creación y poder ejecutar comandos "docker exec" en él, debe crearlo con los indicadores "-it" en el comando docker create.
joanlofe
8

Esta es una respuesta combinada que inventé usando la respuesta CDR LDN anterior y la respuesta que encontré aquí .

El siguiente ejemplo inicia un contenedor Arch Linux desde una imagen, y luego se instala giten ese contenedor utilizando la pacmanherramienta:

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"

Eso es todo.

imriss
fuente
5

Si está intentando ejecutar el script de shell, debe ejecutarlo como bash.

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

Canalizar un comando a stdin

Debe eliminar el -tpara que funcione:

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

Esto puede ser más conveniente que usar las opciones de CLI a veces.

Probado con:

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

luego en otro caparazón:

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

Luego en el primer caparazón:

ls -l myfile

Probado en Docker 1.13.1, host Ubuntu 16.04.

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

Asumiendo que la imagen está usando el punto de entrada predeterminado /bin/sh -c, la ejecución /bin/bashsaldrá inmediatamente en modo demonio ( -d). Si desea que este contenedor ejecute un shell interactivo, use en -itlugar de -d. Si desea ejecutar comandos arbitrarios en un contenedor que generalmente ejecuta otro proceso, puede intentarlo nsentero nsinit. Eche un vistazo a https://blog.codecentric.de/en/2014/07/enter-docker-container/ para más detalles.

Andreas Steffan
fuente
3

Lamentablemente, es imposible anular ENTRYPOINTcon argumentos docker run --entrypointpara lograr este objetivo.

Nota: puede anular la configuración de ENTRYPOINT usando --entrypoint, pero esto solo puede establecer el binario en exec (no se usará sh -c).

wieczorek1990
fuente
3

Me gustaría señalar que la respuesta principal es un poco engañosa.

El problema con la ejecución docker runes que cada vez se crea un nuevo contenedor. Sin embargo, hay casos en los que nos gustaría volver a visitar los contenedores antiguos o no ocupar espacio con contenedores nuevos.

(Dado clever_bardeenes el nombre del contenedor creado ...)

En el caso de OP, asegúrese de que la imagen del acoplador se ejecute primero ejecutando el siguiente comando:

docker start clever_bardeen

Luego, ejecute el contenedor acoplable con el siguiente comando:

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

Para Mac:

$ docker exec -it <container-name> sh

si quieres conectarte como usuario root:

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

Respuesta simple: comenzar y adjuntar al mismo tiempo. En este caso, está haciendo exactamente lo que pidió.

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

asegúrate de cambiar <CONTAINER_ID/CONTAINER_NAME>

usuario353305
fuente
1
# docker exec -d container_id command 

Ex:

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

Estoy ejecutando el contenedor de Windows y necesito buscar dentro del contenedor de la ventana acoplable los archivos y carpetas creados y copiados.

Para hacer eso, utilicé el siguiente comando docker entrypoint para que el símbolo del sistema se ejecute dentro del contenedor o se adjunte al contenedor.

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

Eso me ayudó tanto al símbolo del sistema adjuntar al contenedor como a mantener vivo el contenedor. :)

Jenish Rabadiya
fuente
0

Una forma rápida de reanudar y acceder al contenedor salido más recientemente:

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

Usualmente uso esto:

    docker exec -it my-container-name bash

para interactuar continuamente con un contenedor en ejecución.

Amin Shojaei
fuente