¿Puedo ejecutar varios programas en un contenedor Docker?

150

Estoy tratando de entender Docker desde el punto de implementar una aplicación que está destinada a ejecutarse en los usuarios en el escritorio. Mi aplicación es simplemente una aplicación web de matraz y una base de datos mongo. Normalmente, instalaría tanto en una VM como reenviaría un puerto host a la aplicación web de invitado. Me gustaría probar Docker, pero no estoy seguro de cómo debo usar más de un programa. La documentación dice que solo puede haber ENTRYPOINT, entonces, ¿cómo puedo tener Mongo y mi aplicación de matraz? ¿O deben estar en contenedores separados, en cuyo caso, cómo se hablan y cómo facilita la distribución de la aplicación?

nickponline
fuente
2
Spot: me hace preguntarme por qué Docker era tan popular ... (proceso único ...?) - pero veamos qué nos dicen las respuestas ...
javadba

Respuestas:

120

Solo puede haber un PUNTO DE ENTRADA, pero ese objetivo suele ser un script que inicia la mayor cantidad de programas necesarios. También puede usar, por ejemplo, Supervisord o similar para encargarse de lanzar múltiples servicios dentro de un solo contenedor. Este es un ejemplo de un contenedor docker que ejecuta mysql, apache y wordpress dentro de un solo contenedor .

Diga: Tiene una base de datos que usa una sola aplicación web. Entonces, probablemente sea más fácil ejecutar ambos en un solo contenedor.

Si tiene una base de datos compartida que es utilizada por más de una aplicación, sería mejor ejecutar la base de datos en su propio contenedor y las aplicaciones cada una en sus propios contenedores.

Hay al menos dos posibilidades de cómo las aplicaciones pueden comunicarse entre sí cuando se ejecutan en diferentes contenedores:

  1. Use puertos IP expuestos y conéctese a través de ellos.
  2. Las versiones recientes de docker admiten enlaces .
vesako
fuente
1
Parece que las nuevas versiones de Docker ahora admiten redes de contenedores Docker .
jpierson
Docker ahora admite ejecutar Supervisor, lo que le permite separar el comportamiento de cada proceso, como autorestart = true, stdout_logfile, stderr_logfile, etc. Consulte docs.docker.com/engine/admin/using_supervisord
Andreas Lundgren
44
Definitivamente, no recomendaría intentar ejecutar la aplicación web y mongodb en el mismo contenedor en este ejemplo. Hay buenos casos de uso de supervisión o procesos similares a init en Docker, pero este no es parte de ellos. Es mucho más simple usar docker-compose para ejecutar los dos servicios en contenedores separados.
nicolas-van
@ nicolas-van ¿por qué es más simple? ¿Es porque si la base de datos muere, puedo reiniciar el contenedor de la base de datos en lugar de tener que reiniciar todo?
brillante
Las aplicaciones en la misma máquina también pueden comunicarse a través de sockets de dominio Unix . Máximo rendimiento garantizado.
Escéptico Jule
21

Tenía un requisito similar de ejecutar una pila LAMP, Mongo DB y mis propios servicios

Docker es una virtualización basada en el sistema operativo, por lo que aísla su contenedor alrededor de un proceso en ejecución, por lo tanto, requiere al menos un proceso que se ejecute en FOREGROUND.

Por lo tanto, proporciona su propio script de inicio como punto de entrada, por lo que su script de inicio se convierte en un script de imagen Docker extendido, en el que puede apilar cualquier número de servicios hasta que SE INICIE AL MENOS UN SERVICIO ANTERIOR, QUE DEMASIADO HACIA EL FINAL

Entonces mi archivo de imagen Docker tiene dos líneas a continuación al final:

COPY myStartupScript.sh /usr/local/myscripts/myStartupScript.sh
CMD ["/bin/bash", "/usr/local/myscripts/myStartupScript.sh"]

En mi script ejecuto todos los MySQL, MongoDB, Tomcat, etc. Al final ejecuto mi Apache como un subproceso en primer plano.

source /etc/apache2/envvars
/usr/sbin/apache2 -DFOREGROUND

Esto me permite iniciar todos mis servicios y mantener vivo el contenedor con el último servicio iniciado en primer plano

Espero eso ayude

ACTUALIZACIÓN : desde la última vez que respondí a esta pregunta, han surgido cosas nuevas como Docker compose , que puede ayudarlo a ejecutar cada servicio en su propio contenedor, pero aunarlas como dependencias entre esos servicios, intente saber más sobre docker-compose y úselo, es una forma más elegante a menos que su necesidad no coincida con él.

Basav
fuente
6

Estoy totalmente en desacuerdo con algunas soluciones anteriores que recomiendan ejecutar ambos servicios en el mismo contenedor. Está claramente establecido en la documentación que no es recomendable :

En general, se recomienda que separe las áreas de preocupación utilizando un servicio por contenedor. Ese servicio puede bifurcarse en múltiples procesos (por ejemplo, el servidor web Apache inicia múltiples procesos de trabajo). Está bien tener múltiples procesos, pero para obtener el mayor beneficio de Docker, evite que un contenedor sea responsable de múltiples aspectos de su aplicación general. Puede conectar varios contenedores utilizando redes definidas por el usuario y volúmenes compartidos.

Hay buenos casos de uso para supervisores o programas similares, pero ejecutar una aplicación web + base de datos no forma parte de ellos.

Definitivamente debe usar docker-compose para hacer eso y orquestar múltiples contenedores con diferentes responsabilidades.

nicolas-van
fuente
2
Este es un comentario, no una respuesta. Considere agregar una explicación y / o enlaces para respaldar esta posición. De lo contrario, no es útil.
Ivan Ivanov el
1
Esta es una respuesta en el sentido de que la mejor recomendación que puedo dar en tal caso de uso es usar docker-compose. De todos modos, tienes razón en que podría darte más enlaces a recomendaciones oficiales. Lo actualizaré.
nicolas-van
La pregunta es sobre la ejecución de 2 procesos en un contenedor, por lo tanto, no le importan las mejores prácticas. Le daré un ejemplo: tuve que ejecutar rabbitmq dentro de una imagen basada en PhotonOS y un proceso de Java también ... Así que usé un script de entrada y lo utilicé como ENTRYPOINT :)
Vallerious
La pregunta original no es una pregunta genérica sobre la viabilidad técnica de ejecutar dos procesos en un contenedor Docker. Establece un caso de uso específico que es el despliegue de una aplicación Python junto con una base de datos MongoDB. Y, para ese caso de uso, la mejor recomendación es desalentar el uso de un solo contenedor y recomendar el uso de docker-compose.
nicolas-van
5

Pueden estar en contenedores separados y, de hecho, si la aplicación también estuviera destinada a ejecutarse en un entorno más grande, probablemente lo estarían.

Un sistema de contenedores múltiples requeriría más orquestación para poder mostrar todas las dependencias requeridas, aunque en Docker v0.6.5 +, hay una nueva instalación para ayudar con eso integrado en Docker: vinculación . Sin embargo, con una solución de múltiples máquinas, todavía es algo que debe arreglarse desde fuera del entorno Docker.

Con dos contenedores diferentes, las dos partes aún se comunican a través de TCP / IP, pero a menos que los puertos se hayan bloqueado específicamente (no recomendado, ya que no podría ejecutar más de una copia), tendría que pasar el nuevo puerto que la base de datos ha sido expuesta en cuanto a la aplicación, para que pueda comunicarse con Mongo. Esto es nuevamente, algo con lo que Linking puede ayudar.

Para una instalación pequeña y más simple, donde todas las dependencias van en el mismo contenedor, también es posible tener tanto la base de datos como el tiempo de ejecución de Python iniciado por el programa que inicialmente se llama ENTRYPOINT. Esto puede ser tan simple como un script de shell o algún otro controlador de proceso: Supervisord es bastante popular y existen varios ejemplos en los Dockerfiles públicos.

Alister Bulman
fuente
3

Estoy de acuerdo con las otras respuestas de que es preferible usar dos contenedores, pero si está decidido a agrupar múltiples servicios en un solo contenedor, puede usar algo como la supervisión.

en Hipache, por ejemplo, el Dockerfile incluido ejecuta supervisord y el archivo supervisord.conf especifica que se ejecuten tanto hipache como redis-server.

ben schwartz
fuente
2

Docker proporciona un par de ejemplos sobre cómo hacerlo. La opción ligera es:

Coloque todos sus comandos en una secuencia de comandos de contenedor, completa con información de prueba y depuración. Ejecute el script de envoltura como su CMD. Este es un ejemplo muy ingenuo. Primero, el script de envoltura:

#!/bin/bash

# Start the first process
./my_first_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_first_process: $status"
  exit $status
fi

# Start the second process
./my_second_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_second_process: $status"
  exit $status
fi

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container will exit with an error
# if it detects that either of the processes has exited.
# Otherwise it will loop forever, waking up every 60 seconds

while /bin/true; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they will exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit -1
  fi
  sleep 60
done

A continuación, el Dockerfile:

FROM ubuntu:latest
COPY my_first_process my_first_process
COPY my_second_process my_second_process
COPY my_wrapper_script.sh my_wrapper_script.sh
CMD ./my_wrapper_script.sh
OzNetNerd
fuente
2

Puede ejecutar 2 procesos en primer plano utilizando wait. Simplemente haga un script bash con el siguiente contenido. Por ejemplo start.sh:

# runs 2 commands simultaneously:

mongod & # your first application
P1=$!
python script.py & # your second application
P2=$!
wait $P1 $P2

En su Dockerfile, comience con

CMD bash start.sh
Sam
fuente
0

Si una secuencia de comandos dedicada parece demasiada sobrecarga, puede generar procesos separados explícitamente con sh -c. Por ejemplo:

CMD sh -c 'mini_httpd -C /my/config -D &' \
 && ./content_computing_loop
Rafael
fuente