¿Cómo iniciar automáticamente un servicio cuando se ejecuta un contenedor acoplable?

157

Tengo un Dockerfile para instalar el servidor MySQL en un contenedor, que luego comienzo así:

sudo docker run -t -i 09d18b9a12be /bin/bash

Pero el servicio MySQL no se inicia automáticamente, tengo que ejecutarlo manualmente (desde dentro del contenedor):

service mysql start

¿Cómo inicio automáticamente el servicio MySQL cuando ejecuto el contenedor docker?

mtmacdonald
fuente
1
no, para un servicio simple, no se necesita un supervisor, es complicado para el usuario principiante
Larry Cai
8
es posible que desee copiar el dockerfile aquí en lugar de vincularlo a un archivo que ya no existe
neo112
El artículo de Docker sobre supervisión ahora está aquí: docs.docker.com/config/containers/multi-service_container. Utilicé el comando && tail para que mi servicio funcione, pero necesitaba agregar "--cap-add SYS_PTRACE" al docker. ejecutar comando
Ted Cahall

Respuestas:

205

Primero, hay un problema en su Dockerfile:

RUN service mysql restart && /tmp/setup.sh

Las imágenes de Docker no guardan los procesos en ejecución. Por lo tanto, su RUNcomando se ejecuta solo durante la docker buildfase y se detiene después de completar la compilación. En su lugar, debe especificar el comando cuando el contenedor se inicia utilizando los comandos CMDo ENTRYPOINTcomo se muestra a continuación:

CMD mysql start

En segundo lugar, el contenedor acoplable necesita un proceso (último comando) para seguir ejecutándose; de ​​lo contrario, el contenedor saldrá / se detendrá. Por lo tanto, el service mysql startcomando normal no se puede usar directamente en el Dockerfile.

Solución

Hay tres formas típicas de mantener el proceso en ejecución:

  • Usar el servicecomando y agregar un comando sin fin después de eso comotail -F

    CMD service mysql start && tail -F /var/log/mysql/error.log
    

Esto se prefiere a menudo cuando tiene un único servicio en ejecución, ya que hace que el registro de salida sea accesible para la ventana acoplable.

  • O use el comando de primer plano para hacer esto

    CMD /usr/bin/mysqld_safe
    

Esto funciona solo si hay un script como mysqld_safe.

  • O envuelve tus scripts start.shy pon esto al final

    CMD /start.sh
    

Esto es mejor si el comando debe realizar una serie de pasos, nuevamente, /start.shdebe seguir ejecutándose.

Nota

Para el principiante supervisordno se recomienda el uso. Honestamente, es exagerado. Es mucho mejor usar un solo servicio / comando único para el contenedor.

Por cierto: consulte https://registry.hub.docker.com para ver las imágenes existentes de MySQL Docker para referencia

Larry Cai
fuente
¿Cómo reiniciaría el servicio una vez iniciado en el contenedor docker?
K - La toxicidad en SO está creciendo.
3
@KarlMorrisondocker exec -it <CONTAINER NAME> mysql /etc/init.d/mysqld restart
kaiser
1
No recomendaría ajustar el registro de errores de MySQL para determinar si la base de datos se está ejecutando o no. En la mayoría de las configuraciones de mysqld, el servidor se recuperará de los errores y, en el proceso, el registro de errores se cerrará y luego se volverá a abrir. Tampoco estoy seguro de que su cola -F funcione para usted en todos o incluso en algunos casos.
Brian Aker
No estoy seguro de por qué, pero la primera opción de solución funciona bien para el script de servicio. Cuando no use tail, fallará, aunque se inicie el servicio (al menos para el servicio tomcat7). Con cola funciona. Para ambos casos, debe usar el interruptor cap_add (- cap-add SYS_PTRACE para ejecutar) con al menos SYS_PTRACE
zhrist
1
no, ver más en stackoverflow.com/questions/46800594/…
Larry Cai
73

En su Dockerfile, agregue en la última línea

ENTRYPOINT service ssh restart && bash

Esto funciona para mi

Y este es el resultado:

root@ubuntu:/home/vagrant/docker/add# docker run -i -t ubuntu
 * Restarting OpenBSD Secure Shell server sshd   [ OK ]                                                                      
root@dccc354e422e:~# service ssh status
 * sshd is running
Jia
fuente
2
Esto es bueno, pero creo que no puede tener un contenedor separado de esta manera.
mdob
1
Esto funciono muy bien para mi. Estaba teniendo problemas para que Nginx 1.8 se iniciara automáticamente. Puede ser útil agregar lo siguiente: RUN echo "daemon off"; >> /etc/nginx/nginx.conf EJECUTAR ln -sf / dev / stdout /var/log/nginx/access.log EJECUTAR ln -sf / dev / stderr /var/log/nginx/error.log
Lionel Morrison
1
¿Hay algún inconveniente en esta solución?
srph
2
Iniciar Bash finalmente es una mala idea cuando desea detener sus servicios con gracia, porque de esta manera el contactor de Docker no puede ser detenido docker stopo con docker restartgracia, solo puede ser asesinado.
Mohammed Noureldin
Estaba trabajando en el empaquetador para crear imágenes de acoplador y esto parece solucionar mi problema con el contenedor en el archivo del empacador. "cambios": ["ENTRYPOINT service nginx start && / bin / bash"]
karthik101
8

¡Sencillo! Agregar al final del dockerfile:

ENTRYPOINT service mysql start && /bin/bash
Thiago
fuente
Esta es la mejor respuesta que resuelve mi problema actual con el Contenedor Docker: Docker version 18.09.7, build 2d0083dsin && /bin/bashel servicio se detendrá de inmediato
Largo
7

Hay otra forma de hacerlo que siempre he encontrado que es más legible.

Digamos que quieres iniciar rabbitmq y mongodb cuando lo ejecutas y luego tu CMD se vería así:

CMD /etc/init.d/rabbitmq-server start && \
    /etc/init.d/mongod start

Ya que solo puedes tener uno CMDporDockerfile truco, es concatenar todas las instrucciones &&y luego usarlas \para cada comando para comenzar una nueva línea.

Si termina agregando a muchos de ellos, le sugiero que ponga todos sus comandos en un archivo de script y lo inicie como sugirió @ larry-cai:

CMD /start.sh
Francesco Casula
fuente
3

En mi caso, tengo una aplicación web PHP servida por Apache2 dentro del contenedor acoplable que se conecta a una base de datos back-end MYSQL. La solución de Larry Cai funcionó con modificaciones menores. Creé un entrypoint.sharchivo dentro del cual administro mis servicios. Creo que crear un entrypoint.shcuando tienes más de un comando para ejecutar cuando se inicia tu contenedor es una forma más limpia de arrancar el acoplador.

#!/bin/sh

set -e

echo "Starting the mysql daemon"
service mysql start

echo "navigating to volume /var/www"
cd /var/www
echo "Creating soft link"
ln -s /opt/mysite mysite

a2enmod headers
service apache2 restart

a2ensite mysite.conf
a2dissite 000-default.conf
service apache2 reload

if [ -z "$1" ]
then
    exec "/usr/sbin/apache2 -D -foreground"
else
    exec "$1"
fi
Mr. Doomsbuster
fuente
Simplemente colóquelo junto a su Dockerfile. Luego, en su Dockerfile, debe tener una instrucción que copie este archivo en la ubicación deseada. Luego, señala la ENTRYPOINT ['your location']instrucción al archivo de script. Sin embargo, recuerde establecer los permisos de ejecución en su script. COPY entrypoint.sh /entrypoint.sh RUN chmod 755 /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"]. En este ejemplo, copié mi punto de entrada al directorio raíz en el contenedor docker.
Sr. Doomsbuster
¿Dónde está Dockerfile?
Viktor Joras
3

Tengo el mismo problema cuando quiero iniciar automáticamente el servicio ssh. Encontré que agregar

/etc/init.d/ssh start
a
~ / .bashrc
puede resolverlo, pero solo lo abre con bash lo hará.

Weiping.Chen
fuente
1

Agrego el siguiente código a /root/.bashrc para ejecutar el código solo una vez,

Confirme el contenedor con la imagen antes de ejecutar este script; de lo contrario, el archivo 'docker_services' se creará en las imágenes y no se ejecutará ningún servicio.

if [ ! -e /var/run/docker_services ]; then
    echo "Starting services"
    service mysql start
    service ssh start
    service nginx start
    touch /var/run/docker_services
fi
usuario136685
fuente
1

Así es como inicio automáticamente el servicio MySQL cada vez que se ejecuta el contenedor docker.

En mi caso, necesito ejecutar no solo MySQL sino también PHP, Nginx y Memcached

Tengo las siguientes líneas en Dockerfile

RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
EXPOSE 3306
CMD service mysql start && service php-fpm start && nginx -g 'daemon off;' && service memcached start && bash

Agregar && bash mantendría a Nginx, MySQL, PHP y Memcached ejecutándose dentro del contenedor.

Chris
fuente
1

Esto no funciona CMD service mysql start && /bin/bash

Esto no funciona CMD service mysql start ; /bin/bash ;

- Supongo que el modo interactivo no admitiría el primer plano.

Esto funciona !! CMD service nginx start ; while true ; do sleep 100; done;

Esto funciona !! CMD service nginx start && tail -F /var/log/nginx/access.log

tenga cuidado con que debe usar docker run -p 80:80 nginx_bashsin parámetro de comando.

usuario3073309
fuente
0

La siguiente documentación del sitio web de Docker muestra cómo implementar un servicio SSH en un contenedor de Docker. Debe ser fácilmente adaptable para su servicio:

Aquí también se ha hecho una variación de esta pregunta:

Zammalad
fuente
nsenter tool es otro enfoque para ingresar en un contenedor, sin requerir la instalación del servidor SSH: github.com/jpetazzo/nsenter . Pero este enfoque requiere un acceso a su host Docker (por lo general, el acceso SSH es suficiente).
Fabien Balageas
El enlace docs.docker.com/sorry/#/examples/running_ssh_service no funciona. ¿Puedes por favor actualizarlo?
Ankur
0
docker export -o <nameOfContainer>.tar <nameOfContainer>

Es posible que necesite podar el contenedor existente usando la podadora de Docker ...

Importar con modificaciones requeridas:

cat <nameOfContainer>.tar | docker import -c "ENTRYPOINT service mysql start && /bin/bash" - <nameOfContainer>

Ejecute el contenedor, por ejemplo, con la opción siempre reiniciar para asegurarse de que se reanudará automáticamente después del reciclaje de host / demonio:

docker run -d -t -i --restart always --name <nameOfContainer> <nameOfContainer> /bin/bash

Nota al margen: En mi opinión, lo razonable es comenzar solo el servicio cron dejando el contenedor lo más limpio posible y luego modificar crontab o cron.hourly, .daily, etc. con los scripts de verificación / monitoreo correspondientes. La razón es que solo confía en un demonio y, en caso de cambios, es más fácil con ansible o puppet redistribuir scripts cron en lugar de rastrear servicios que comienzan en el arranque.

Daniel
fuente