¿Por qué el contenedor Docker sale inmediatamente?

240

Ejecuto un contenedor en segundo plano usando

 docker run -d --name hadoop h_Service

Sale rápidamente. Pero si corro en primer plano, funciona bien. Revisé los registros usando

docker logs hadoop

No hubo error. ¿Algunas ideas?

DOCKERFILE

 FROM java_ubuntu_new
 RUN wget http://archive.cloudera.com/cdh4/one-click-install/precise/amd64/cdh4-repository_1.0_all.deb
 RUN dpkg -i cdh4-repository_1.0_all.deb
 RUN curl -s http://archive.cloudera.com/cdh4/ubuntu/precise/amd64/cdh/archive.key | apt-key add -
 RUN  apt-get update
 RUN apt-get install -y hadoop-0.20-conf-pseudo
 RUN dpkg -L hadoop-0.20-conf-pseudo
 USER hdfs
 RUN hdfs namenode -format
 USER root
 RUN apt-get install -y sudo
 ADD . /usr/local/
 RUN chmod 777 /usr/local/start-all.sh
 CMD ["/usr/local/start-all.sh"]

start-all.sh

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start
 /etc/init.d/hadoop-hdfs-datanode start
 /etc/init.d/hadoop-hdfs-secondarynamenode start
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start
 /bin/bash
Gibbs
fuente
1
La regla de oro es que debes evitar que tus servidores dockerizados hagan demonios. La mayoría de los paquetes de servidor tienen opciones para forzarlos en primer plano, ya que la demonización es el caso normal.
Arnaud Meuret
Lo que sea que espere lograr, chmod 777es inseguro e incorrecto. Debería volver a los permisos sanos (probablemente 755 en este caso).
tripleee el

Respuestas:

125

Un contenedor acoplable sale cuando finaliza su proceso principal.

En este caso, saldrá cuando start-all.shfinalice su secuencia de comandos. No sé lo suficiente sobre hadoop para decirle cómo hacerlo en este caso, pero debe dejar algo ejecutándose en primer plano o utilizar un administrador de procesos como runit o supervisor para ejecutar los procesos.

Creo que debes equivocarte si funciona si no lo especificas -d; Debería tener exactamente el mismo efecto. Sospecho que lo lanzó con un comando ligeramente diferente o con el -itque cambiará las cosas.

Una solución simple puede ser agregar algo como:

while true; do sleep 1000; done

hasta el final del guión. Sin embargo, no me gusta esto, ya que el script realmente debería estar monitoreando los procesos que inició.

(Debo decir que robé ese código de https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh )

Adrian Mouat
fuente
218

Esto hizo el truco para mí:

docker run -dit ubuntu

Después de eso, verifiqué los procesos que se ejecutan usando:

docker ps -a

Para volver a colocar el contenedor

docker attach CONTAINER_NAME

SUGERENCIA: para salir sin detener el tipo de contenedor: ^P^Q

camposer
fuente
15
@Tommy, de docs.docker.com/engine/reference/commandline/run -d, --detach Modo separado: ejecute el comando en segundo plano, -i, --interactive Mantenga abierto STDIN incluso si no está conectado, -t, - -tty Asignar un pseudo-TTY -dites solo una abreviatura
3
@ am17torres correcto, lo siento déjame aclarar mi pregunta confusa; d está separado e i es interactivo, por lo que la combinación de d e i me resulta confusa. Pensé que d debía lanzarlo como un proceso en segundo plano (no interactivo).
Tommy
2
@Tommy Cuando se combinan estas opciones, el contenedor entrará en modo interactivo en segundo plano .
Yon
2
@Tommy, @ am17torres -dies el mínimo requerido, la -topción es redundante cuando se usa -dsi entiendo correctamente
Renaud
2
En realidad, no podrás ver tu mensaje si vuelves a conectarlo sin -thabilitarlo ... pero como generalmente hago execuna nueva fiesta cada vez que no me doy cuenta. He tenido problemas para desconectarme de una Mac, pero tal vez estoy haciendo esto mal ..
Renaud
65

Me gustaría extender o atreverme a decir, mejorar la respuesta mencionada por camposer

Cuando corres

docker run -dit ubuntu

básicamente está ejecutando el contenedor en segundo plano en modo interactivo.

Cuando conecta y sale del contenedor mediante CTRL + D (la forma más común de hacerlo), detiene el contenedor porque acaba de matar el proceso principal que inició su contenedor con el comando anterior.

Aprovechando un contenedor que ya se está ejecutando, simplemente bifurcaría otro proceso de bash y obtendría un pseudo TTY ejecutando:

docker exec -it <container ID> /bin/bash
Krishna Gupta
fuente
29

cada vez que quiero que un contenedor permanezca activo después de terminar la ejecución del script, agrego

&& tail -f /dev/null

al final del comando. Entonces debería ser:

/usr/local/start-all.sh && tail -f /dev/null
Thiago Ramos
fuente
19

¿Por qué el contenedor Docker sale inmediatamente?

Si desea forzar la imagen para que se cuelgue (para depurar algo o examinar el estado del sistema de archivos), puede anular el punto de entrada para cambiarlo a un shell:

docker run -it --entrypoint=/bin/bash myimagename
RJFalconer
fuente
18

Un buen enfoque sería iniciar sus procesos y servicios ejecutándolos en segundo plano y usar el wait [n ...]comando al final de su secuencia de comandos. En bash, el comando de espera obliga al proceso actual a:

Espere cada proceso especificado y devuelva su estado de finalización. Si no se proporciona n, se esperan todos los procesos secundarios actualmente activos y el estado de retorno es cero.

Tengo esta idea del guión de inicio de Sébastien Pujadas para su construcción de alces .

Tomando de la pregunta original, su start-all.sh se vería así ...

 #!/usr/bin/env bash
 /etc/init.d/hadoop-hdfs-namenode start &
 /etc/init.d/hadoop-hdfs-datanode start &
 /etc/init.d/hadoop-hdfs-secondarynamenode start &
 /etc/init.d/hadoop-0.20-mapreduce-tasktracker start &
 sudo -u hdfs hadoop fs -chmod 777 /
 /etc/init.d/hadoop-0.20-mapreduce-jobtracker start &
 wait
Brian Olsen
fuente
5

Agregue esto al final de Dockerfile:

CMD tail -f /dev/null

Archivo Docker de muestra:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null

Referencia

Kert Kukk
fuente
CMD tail -f /dev/nulllo atraviesa sh -c "...". ¿Podemos usar el execformulario en su lugar? Es decirCMD ["tail", "-f", "/dev/null"]
Meglio
4

Mi práctica es en el Dockerfile iniciar un shell que no saldrá inmediatamente CMD [ "sh", "-c", "service ssh start; bash"], luego se ejecutará docker run -dit image_name. De esta manera, el servicio (ssh) y el contenedor se están ejecutando.

León
fuente
1

Añadí readdeclaración concha al final. Esto mantiene el proceso principal del contenedor (script de shell de inicio) en ejecución.

Jaydeep Ranipa
fuente
1

Agregando

exec "$@"

Al final de mi script de shell fue mi solución!

Adam k
fuente
Eso solo significa que ejecutará su cmd, si su cmd es simplemente 'bash', entonces todavía no funcionará
Shardj
1

Si verifica Dockerfile desde contenedores, por ejemplo fballiano / magento2-apache-php

verá que al final de su archivo agrega el siguiente comando: mientras es verdadero; duerme 1; hecho

Ahora, lo que recomiendo es que hagas esto

docker container ls --all | grep 127

Luego, verá si la imagen de su ventana acoplable tuvo un error, si sale con 0, entonces probablemente necesite uno de estos comandos que se suspenderá para siempre.

xavierbaez
fuente
0

Hay muchas formas posibles de hacer que una ventana acoplable salga de inmediato. Para mí, fue el problema con mi Dockerfile. Hubo un error en ese archivo. Tenía en ENTRYPOINT ["dotnet", "M4Movie_Api.dll]lugar de ENTRYPOINT ["dotnet", "M4Movie_Api.dll"]. Como puede ver, me había perdido una cita (") al final.

Para analizar el problema, inicié mi contenedor y rápidamente lo conecté para poder ver cuál era el problema exacto.

C:\SVenu\M4Movie\Api\Api>docker start 4ea373efa21b


C:\SVenu\M4Movie\Api\Api>docker attach 4ea373efa21b

Donde 4ea373efa21b es mi id de contenedor. Esto me lleva al problema real.

ingrese la descripción de la imagen aquí

Después de encontrar el problema, tuve que construir, restaurar y publicar mi contenedor nuevamente.

Sibeesh Venu
fuente
0

Viniendo de duplicados, no veo ninguna respuesta aquí que aborde el antipatrón muy común de ejecutar su carga de trabajo principal como un trabajo en segundo plano, y luego me pregunto por qué Docker sale.

En términos simples, si tienes

my-main-thing &

luego saque el &para ejecutar el trabajo en primer plano o agregue

wait

al final del script para que espere todos los trabajos en segundo plano.

Seguirá saliendo si la carga de trabajo principal sale, así que quizás ejecute esto en un while truebucle para forzarlo a reiniciarse para siempre:

while true; do
    my-main-thing &
    other things which need to happen while the main workload runs in the background
    maybe if you have such things
    wait
done

(Nótese también cómo escribir while true. Es común ver cosas tontas como while [ true ]o while [ 1 ]lo que ocurra por casualidad a trabajar, pero no me refiero a lo que el autor probablemente imaginó que debería significar).

tripleee
fuente
0

Debe ejecutarlo con la bandera -d para dejarlo ejecutándose como daemon en segundo plano.

docker run -d -it ubuntu bash

Vivek
fuente
-5

Puede ejecutar el contenedor con este indicador de reinicio.

docker run -d --name=<some-name> -p xxxx:xxxx ... <image-name> --restart=unless-stopped
Akmal Ahmed
fuente
-8

Como la imagen es un linux, una cosa que debe verificar es asegurarse de que todos los scripts de shell utilizados en el contenedor tengan terminaciones de línea unix. Si tienen un ^ M al final, entonces son terminaciones de línea de Windows. Una forma de solucionarlos es con dos2unix en /usr/local/start-all.sh para convertirlos de Windows a Unix. Ejecutar la ventana acoplable en modo interactivo puede ayudar a resolver otros problemas. Podría tener un error tipográfico de nombre de archivo o algo así. ver https://en.wikipedia.org/wiki/Newline

dskow
fuente