¿Cómo iniciar un contenedor Docker detenido con un comando diferente?

251

Me gustaría iniciar un contenedor Docker detenido con un comando diferente, ya que el comando predeterminado se bloquea, lo que significa que no puedo iniciar el contenedor y luego usar 'docker exec'.

Básicamente me gustaría comenzar un shell para poder inspeccionar el contenido del contenedor.

¡Por suerte creé el contenedor con la opción -it!

aaa90210
fuente

Respuestas:

380

Encuentra tu ID de contenedor detenido

docker ps -a

Confirmar el contenedor detenido:

Este comando guarda el estado del contenedor modificado en una nueva imagen user/test_image

docker commit $CONTAINER_ID user/test_image

Iniciar / ejecutar con un punto de entrada diferente:

docker run -ti --entrypoint=sh user/test_image

Descripción del argumento del punto de entrada: https://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

Nota:

Los pasos anteriores simplemente inician un contenedor detenido con el mismo estado del sistema de archivos. Eso es genial para una investigación rápida. Pero las variables de entorno, la configuración de red, los volúmenes adjuntos y otro personal no se heredan, debe especificar todos estos argumentos explícitamente.

Los pasos para iniciar un contenedor detenido se tomaron prestados desde aquí: (último comentario) https://github.com/docker/docker/issues/18078

Dmitriusan
fuente
1
no, las imágenes son de solo lectura. Guarda el estado del contenedor modificado en una nueva imagen test_image
Dmitriusan
44
esto pierde casi toda la configuración sobre env, volúmenes, UID, ... Todo lo que tiene en común con el contenedor detenido es el sistema de archivos (que tal vez sea suficiente para algunos)
Florian Klein
44
Sería genial si de alguna manera pudiera obtener el mismo entorno, configuración de red, volúmenes adjuntos. ¿Es posible convertir la inspectsalida en una configuración que se utiliza con la ejecución posterior?
Oteo
2
@Webman, sí, pero eso no es cierto para los volúmenes que se montaron antes de detener un contenedor. Tendrá que adjuntar los mismos volúmenes explícitamente cuando inicie el contenedor la próxima vez
Dmitriusan
1
@ EmreTapcı, creo que hacerlo va en contra de la ideología de Docker. Los contenedores están destinados a ser una entidad de uso individual, en contraste con las máquinas virtuales. Puede intentar seguir la respuesta aaa90210 , pero sería un truco.
Dmitriusan el
126

Edite este archivo (correspondiente a su contenedor detenido):

vi /var/lib/docker/containers/923...4f6/config.json

Cambie el parámetro "Ruta" para apuntar a su nuevo comando, por ejemplo / bin / bash. También puede establecer el parámetro "Args" para pasar argumentos al comando.

Reinicie el servicio acoplable (tenga en cuenta que esto detendrá todos los contenedores en ejecución):

service docker restart

Enumere sus contenedores y asegúrese de que el comando haya cambiado:

docker ps -a

Inicie el contenedor y conéctelo, ¡ahora debería estar en su caparazón!

docker start -ai mad_brattain

Trabajó en Fedora 22 usando Docker 1.7.1.

NOTA: Si su shell no es interactivo (por ejemplo, no creó el contenedor original con la opción -it), puede cambiar el comando a "/ bin / sleep 600" o "/ bin / tail -f / dev / null" para darle tiempo suficiente para hacer "docker exec -it CONTID / bin / bash" como otra forma de obtener un shell.

NOTA2: las versiones más recientes de docker tienen config.v2.json, donde deberá cambiar Entrypoint o Cmd (gracias user60561).

aaa90210
fuente
44
mis ojos. mis ojos. Espero que esta sea una solicitud de función en algún lugar para manejar esto correctamente en Docker.
gertvdijk
2
@AlexeyStrakh, puede intentar ejecutar "/ usr / bin / sleep 600" y luego hacer "docker exec -it / bin / bash" para obtener un shell. Aunque no estoy seguro de cómo poner parámetros en esa variable de ruta. De lo contrario, intente encontrar otro comando que se mantenga vivo el tiempo suficiente para que pueda hacer un ejecutivo, o vea la respuesta de Dmitriusan.
aaa90210
3
esa es la única respuesta realmente precisa a la pregunta: todas las otras propuestas ejecutan un "casi mismo" contenedor, pero se olvidan de los volúmenes, env, UID, ...
Florian Klein
3
En mi caso / usr / bin / sleep no estaba disponible. Tuve éxito con..."Path":"tail","Args":["-f","/dev/null"]...
nevrome
44
Las versiones más recientes de Docker tienen config.v2.json, donde tendrá que cambiar cualquiera Entrypointo Cmd.
user60561
20

Agregue un cheque en la parte superior de su script de Entrypoint

Docker realmente necesita implementar esto como una nueva característica, pero aquí hay otra opción alternativa para situaciones en las que tiene un Punto de entrada que finaliza después del éxito o el fracaso, lo que puede dificultar la depuración.

Si aún no tiene un script de Entrypoint, cree uno que ejecute los comandos que necesite para su contenedor. Luego, en la parte superior de este archivo, agregue estas líneas a entrypoint.sh:

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

Para asegurarse de que se catmantiene la conexión, es posible que deba proporcionar un TTY. Estoy ejecutando el contenedor con mi script de Entrypoint de esta manera:

docker run -t --entrypoint entrypoint.sh image_name

Esto hará que el script se ejecute una vez, creando un archivo que indica que ya se ha ejecutado (en el sistema de archivos virtual del contenedor). Luego puede reiniciar el contenedor para realizar la depuración:

docker start container_name

Cuando reinicie el contenedor, se encontrará el already_ranarchivo, lo que provocará que el script de Entrypoint se detenga cat(que solo espera para siempre la entrada que nunca llegará, pero mantiene vivo el contenedor). Luego puede ejecutar una bashsesión de depuración :

docker exec -i container_name bash

Mientras se ejecuta el contenedor, también puede eliminar already_rany ejecutar manualmente el entrypoint.shscript para volver a ejecutarlo, si necesita depurar de esa manera.

Ethan T
fuente
3
Además, puede hacer que el punto de entrada se ejecute en /bin/shlugar de cat, luego siempre puede ingresar solo reiniciando. ¡Tu solución es genial!
Danny Dulai
4

Mi problema:

  • Empecé un contenedor con docker run <IMAGE_NAME>
  • Y luego agregó algunos archivos a este contenedor
  • Luego cerré el contenedor e intenté iniciarlo nuevamente con el mismo comando que el anterior.
  • Pero cuando revisé los nuevos archivos, faltaban
  • cuando corrí docker ps -apude ver dos contenedores.
  • Eso significa que cada vez que ejecutaba un docker run <IMAGE_NAME>comando, se creaba una nueva imagen

Solución: para trabajar en el mismo contenedor que creó en primer lugar, siga estos pasos

  • docker ps para obtener el contenedor de su contenedor
  • docker container start <CONTAINER_ID> para iniciar el contenedor existente
  • Entonces puedes continuar desde donde te fuiste. p.ejdocker exec -it <CONTAINER_ID> /bin/bash
  • Luego puede decidir crear una nueva imagen a partir de ella
Amit Dudhbade
fuente
Esto no responde la pregunta. El PO quiere saber cómo reiniciar el contenedor pero con argumentos diferentes a los utilizados endocker run <containerID>
CodeBlooded
2

Tomé la respuesta de @ Dmitriusan y la convertí en un alias:

alias docker-run-prev-container = 'prev_container_id = "$ (docker ps -aq | head -n1)" && docker commit "$ prev_container_id" "prev_container / $ prev_container_id" && docker run -it --entrypoint = bash "prev_container" / $ prev_container_id "'

Agregue esto a su ~/.bashrcarchivo de alias, y tendrá un nuevo e ingenioso docker-run-prev-containeralias que lo colocará en un shell en el contenedor anterior.

Útil para la depuración fallida docker builds.

Dean Rather
fuente
2

Esto no es exactamente lo que está pidiendo, pero puede usarlo docker exporten un contenedor detenido si lo único que desea es inspeccionar los archivos.

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR
Lars Christian Jensen
fuente
1

No se especificó si el contenedor está saliendo, solo que su código se bloquea y necesita ver lo que está sucediendo en el contenedor. Si no está saliendo, aquí hay otra solución potencial.

Obtenga la identificación del contenedor con docker ps

docker exec -it 665b4a1e17b6 /bin/sh

Si el punto de entrada se establece en algo problemático, también se puede anular como se sugiere en la respuesta de Dmitriusan. También debe tenerse en cuenta que puede conectarse a cualquier contenedor en ejecución con docker attach. Tantas soluciones diferentes soluciones. Simplemente no veo la necesidad de comprometerme con la imagen. Parece innecesario

Documentos para el ejecutivo de Docker: https://docs.docker.com/engine/reference/commandline/exec/

Documentos para Docker adjuntar: https://docs.docker.com/engine/reference/commandline/attach/

deadbabykitten
fuente
-12

En realidad no estoy de acuerdo con ambas respuestas. Si solo quiere ver qué hay en el contenedor, puede ejecutar este comando para obtener un shell. No es necesario cambiar el punto de entrada en absoluto ni ninguna configuración.

docker run -it <image_name> bash
deadbabykitten
fuente
12
Esto no funciona ya que el operador está preguntando sobre un contenedor, no una imagen.
Peter Vrabel
Supongo que tienes razón, pero no veo una razón para hacerlo. Puede canalizar registros a stdout y docker logs <container_id> --followle dará lo que necesita. Otra alternativa es usar el comando anterior y luego iniciar el servicio de bloqueo en esa imagen con el mismo comando en el dockerfile y depurar desde allí.
deadbabykitten
44
El comando ejecutar crea un nuevo contenedor a partir de una imagen. No inicia un contenedor detenido.
Waleed Abdulla
2
Ummm ... ¿no es que el punto de la ventana acoplable es que cada imagen se puede girar exactamente de la misma manera? Esto niega tu argumento. No NECESITA iniciar un contenedor detenido. Cualquier contenedor es exactamente el mismo, por lo que no importa cuál comience o pare. Él solo está tratando de inspeccionar el contenido. La forma más fácil de hacerlo es atacar y ejecutar el comando o la salida de la tubería del comando a los registros. Ustedes idean las soluciones más complejas para problemas simples a veces.
deadbabykitten
-12
docker container start <CONTAINER_ID>
Oscar Calderón
fuente