web-dev-qa-db-fra.com

Comment démarrer automatiquement un service lors de l'exécution d'un conteneur Docker?

J'ai un Dockerfile pour installer le serveur MySQL dans un conteneur, que je lance ensuite comme ceci:

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

Mais le service MySQL ne démarre pas automatiquement, je dois exécuter manuellement (depuis le conteneur):

service mysql start

Comment démarrer automatiquement le service MySQL lorsque j'exécute le conteneur Docker?

122
mtmacdonald

Premièrement, il y a un problème dans votre Dockerfile:

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

Les images Docker n'enregistrent pas les processus en cours d'exécution. Par conséquent, votre commande RUN ne s'exécute que pendant la phase docker build et s'arrête une fois la construction terminée. Au lieu de cela, vous devez spécifier la commande au démarrage du conteneur à l'aide des commandes CMD ou ENTRYPOINT comme ci-dessous:

CMD mysql start

Deuxièmement, le conteneur docker a besoin d’un processus (dernière commande) pour continuer à fonctionner, sinon le conteneur quittera/s’arrêtera. Par conséquent, la commande normale service mysql start ne peut pas être utilisée directement dans le fichier Docker.

Solution

Il existe trois manières typiques de maintenir le processus en cours: 

  • Utilisation de la commande service et ajout de la commande non-end suivante, telle que tail -F

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

Cela est souvent préférable lorsqu'un seul service est en cours d'exécution, car il rend le journal généré accessible au menu fixe. 

  • Ou utilisez la commande d'avant-plan pour le faire

    CMD /usr/bin/mysqld_safe
    

Cela ne fonctionne que s'il existe un script comme mysqld_safe.

  • Ou enveloppez vos scripts dans start.sh et mettez ceci en fin

    CMD /start.sh
    

Cela est préférable si la commande doit exécuter une série d'étapes. /start.sh doit rester actif.

Remarque

Pour le débutant, utiliser supervisord n'est pas recommandé. Honnêtement, c'est exagéré. Il est bien préférable d’utiliser un seul service/une seule commande pour le conteneur.

BTW: s'il vous plaît vérifier https://registry.hub.docker.com pour les images mysql docker existantes pour référence

171
Larry Cai

Dans votre Dockerfile, ajoutez à la dernière ligne

ENTRYPOINT service ssh restart && bash

Ça marche pour moi

Et voici le résultat:

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
55
Jia

Il y a une autre façon de le faire que j'ai toujours trouvée plus lisible.

Dites que vous voulez démarrer rabbitmq et mongodb lorsque vous l'exécutez, votre CMD ressemblera à ceci:

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

Comme vous ne pouvez avoir qu'une seule CMD par Dockerfile, l'astuce consiste à concaténer toutes les instructions avec &&, puis à utiliser \ pour chaque commande afin de commencer une nouvelle ligne.

Si vous finissez par ajouter beaucoup de celles-ci, je vous suggère de placer toutes vos commandes dans un fichier de script et de le lancer comme indiqué par @ larry-cai:

CMD /start.sh
7
Francesco Casula

Simple! Ajouter à la fin du fichier docker:

ENTRYPOINT service mysql start && /bin/bash
4
Thiago

Dans mon cas, une application Web PHP servie par Apache2 dans le conteneur de menu fixe se connecte à une base de données backend MYSQL. La solution de Larry Cai a fonctionné avec des modifications mineures. J'ai créé un fichier entrypoint.sh dans lequel je gère mes services. Je pense que la création d'un entrypoint.sh lorsque vous avez plus d'une commande à exécuter au démarrage de votre conteneur est une méthode plus simple pour amorcer le menu fixe.

#!/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
3
Mr. Doomsbuster

J'ai le même problème lorsque je veux démarrer automatiquement le service SSH. J'ai trouvé cette annexe

/etc/init.d/ssh start
~/.bashrc
1
Weiping.Chen

Voici comment je lance automatiquement le service MySQL à chaque exécution du conteneur Docker.

Sur mon cas, je dois utiliser non seulement MySQL, mais aussi PHP, Nginx et Memcached.

J'ai les lignes suivantes dans 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

Ajouter && bash garderait Nginx, MySQL, PHP et Memcached en cours d'exécution dans le conteneur.

1
Christopher Buenafe
docker export -o <nameOfContainer>.tar <nameOfContainer>

Peut-être besoin d'élaguer le conteneur existant à l'aide de docker Prune ... 

Importer avec les modifications requises:

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

Exécutez le conteneur par exemple avec l'option always restart pour vous assurer qu'il sera automatiquement repris après le recyclage hôte/démon:

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

Note latérale: À mon avis, il est raisonnable de ne commencer que le service cron en laissant le conteneur le plus propre possible, puis de modifier crontab ou cron.hourly, .daily, etc. Reason is Vous ne vous fiez qu'à un seul démon. En cas de changement, il est plus facile avec ansible ou puppet de redistribuer les scripts cron au lieu de suivre les services qui commencent au démarrage. 

0
Daniel

J'ajoute le code suivant à /root/.bashrc pour l'exécuter une seule fois,

Veuillez valider le conteneur dans l'image avant d'exécuter ce script, sinon le fichier 'docker_services' sera créé dans les images et aucun service ne sera exécuté.

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
0
user136685

La documentation suivante du site Web de Docker explique comment implémenter un service SSH dans un conteneur de menu fixe. Il devrait être facilement adaptable à votre service:

Une variante de cette question a également été posée ici:

0
Zammalad

Cela ne fonctionne pas CMD service mysql start && /bin/bash

Cela ne fonctionne pas CMD service mysql start ; /bin/bash ;

- Je suppose que le mode interactif ne prend pas en charge le premier plan.

Cela marche !! CMD service nginx start ; while true ; do sleep 100; done;

Cela marche !! CMD service nginx start && tail -F /var/log/nginx/access.log

méfiez-vous, vous devriez utiliser docker run -p 80:80 nginx_bash sans paramètre de commande.

0
user3073309