¿Cómo mantener el contenedor Docker funcionando después de iniciar los servicios?


He visto un montón de tutoriales que parecen hacer lo mismo que estoy tratando de hacer, pero por alguna razón mis contenedores Docker salir. Básicamente, estoy configurando un servidor web y algunos demonios dentro de un contenedor Docker. Hago las partes finales de esto a través de un script bash llamado run-all.sh que corro a través de CMD en mi Dockerfile. run-all.sh se ve así:

service supervisor start
service nginx start

Y lo inicio dentro de mi Dockerfile de la siguiente manera:

CMD ["sh", "/root/credentialize_and_run.sh"]

Puedo ver que todos los servicios se inician correctamente cuando corro las cosas manualmente (es decir, llegar a la imagen con-i-t /bin / bash), y todo parece que se ejecuta correctamente cuando corro la imagen, pero sale una vez que termina de iniciar mis procesos. Me gustaría que los procesos se ejecuten indefinidamente, y por lo que entiendo, el contenedor tiene que seguir funcionando para que esto suceda. Sin embargo, cuando corro docker ps -a, veo:

➜  docker_test  docker ps -a
CONTAINER ID        IMAGE                            COMMAND                CREATED             STATUS                      PORTS               NAMES
c7706edc4189        some_name/some_repo:blah   "sh /root/run-all.sh   8 minutes ago       Exited (0) 8 minutes ago                        grave_jones

¿Qué da? ¿Por qué está saliendo? Sé que podría poner un bucle while al final de mi guión bash para seguir así, pero ¿qué es ¿la forma correcta de evitar que salga?

 87
Author: Diogo Gomes, 2014-09-11

7 answers

Esto no es realmente cómo debe diseñar sus contenedores Docker.

Al diseñar un contenedor Docker, se supone que debe construirlo de manera que solo haya un proceso en ejecución (es decir, debe tener un contenedor para Nginx y otro para supervisord o la aplicación que está ejecutando); además, ese proceso debe ejecutarse en primer plano.

El contenedor "saldrá" cuando el proceso mismo salga (en su caso, ese proceso es su script bash).


Sin embargo, si realmente necesita (o desea) ejecutar varios servicios en su contenedor Docker, considere comenzar desde "Docker Base Image", que usa runit como un proceso de pseudo-inicio (runit permanecerá en línea mientras Nginx y Supervisor se ejecutan), que permanecerá en primer plano mientras sus otros procesos hacen lo suyo.

Tienen documentos sustanciales, por lo que debe ser capaz de lograr lo que está tratando de hacer razonablemente fácilmente.

 35
Author: Thomas Orozco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-29 12:53:40

Acabo de tener el mismo problema y me enteré de que si está ejecutando su contenedor con la bandera -t y -d, se sigue ejecutando.

docker run -td <image>

Esto es lo que hacen las banderas (de acuerdo a docker run --help):

-d, --detach=false         Run container in background and print container ID
-t, --tty=false            Allocate a pseudo-TTY

La más importante es la bandera -t. -d solo le permite ejecutar el contenedor en segundo plano.

 55
Author: arne.z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-26 17:50:31

Si está utilizando un Dockerfile, intente:

ENTRYPOINT ["tail", "-f", "/dev/null"]

(Obviamente, esto es solo para desarrolladores, no debería necesitar mantener un contenedor vivo a menos que esté ejecutando un proceso, por ejemplo. nginx...)

 49
Author: Soft Bullets,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-18 11:33:39

La razón por la que se cierra es porque el script de shell se ejecuta primero como PID 1 y cuando se completa, PID 1 desaparece, y docker solo se ejecuta mientras PID 1 lo hace.

Puede usar supervisor para hacer todo, si se ejecuta con la bandera "-n" se le dice que no demonice, por lo que permanecerá como el primer proceso:

CMD ["/usr/bin/supervisord", "-n"]

Y su supervisor.conf:

[supervisord]
nodaemon=true

[program:startup]
priority=1
command=/root/credentialize_and_run.sh
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=false
startsecs=0

[program:nginx]
priority=10
command=nginx -g "daemon off;"
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.log
autorestart=true

Entonces puede tener tantos otros procesos como desee y supervisor se encargará de reiniciarlos si es necesario.

De esa manera podría usar supervisord en casos en los que necesite nginx y php5-fpm y no tiene mucho sentido tenerlos separados.

 34
Author: phazei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-03 23:39:16

Puede ejecutar plain cat sin ningún argumento como menciona bro @ Sa'ad para simplemente mantener el contenedor funcionando [en realidad no hace nada más que esperar la entrada del usuario] (el complemento Docker de Jenkins hace lo mismo)

 28
Author: Serge Velikanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-19 21:01:33

Asegúrese de añadir daemon off; a su nginx.conf o ejecútelo con CMD ["nginx", "-g", "daemon off;"] según la imagen oficial de nginx

Luego use lo siguiente para ejecutar supervisor como servicio y nginx como proceso en primer plano que evitará que el contenedor salga

service supervisor start && nginx

En algunos casos necesitará tener más de un proceso en su contenedor, por lo que forzar al contenedor a tener exactamente un proceso no funcionará y puede crear más problemas en la implementación.

Así que necesitas comprenda las compensaciones y tome su decisión en consecuencia.

 10
Author: iTech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-04 12:58:21

Capture el PID del proceso ngnix en una variable (por ejemplo $NGNIX_PID) y al final del archivo entrypoint haga

wait $NGNIX_PID 

De esa manera, su contenedor debe funcionar hasta que ngnix esté vivo, cuando ngnix se detenga, el contenedor también se detendrá

 3
Author: user2825611,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-18 15:27:39