Pourquoi le conteneur Docker se ferme immédiatement


240

J'exécute un conteneur en arrière-plan en utilisant

 docker run -d --name hadoop h_Service

il sort rapidement. Mais si je cours au premier plan, ça marche bien. J'ai vérifié les journaux en utilisant

docker logs hadoop

il n'y a pas eu d'erreur. Des idées?

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

1
La règle d'or est que vous devez empêcher vos serveurs dockérisés de démoniser. La plupart des packages de serveurs ont des options pour les forcer au premier plan puisque la démonisation est le cas normal.
Arnaud Meuret

Tout ce que vous espérez accomplir chmod 777est incertain et faux. Vous devez revenir à des autorisations raisonnables (probablement 755 dans ce cas).
tripleee

Réponses:


125

Un conteneur Docker se termine lorsque son processus principal se termine.

Dans ce cas, il se fermera à la fin de votre start-all.shscript. Je ne sais pas assez sur hadoop pour vous dire comment le faire dans ce cas, mais vous devez soit laisser quelque chose en cours d'exécution au premier plan, soit utiliser un gestionnaire de processus tel que runit ou supervisord pour exécuter les processus.

Je pense que vous devez vous tromper si cela ne fonctionne pas si vous ne spécifiez pas -d; cela devrait avoir exactement le même effet. Je soupçonne que vous l'avez lancé avec une commande légèrement différente ou en utilisant -itce qui changera les choses.

Une solution simple peut être d'ajouter quelque chose comme:

while true; do sleep 1000; done

à la fin du script. Je n'aime pas cela cependant, car le script devrait vraiment surveiller les processus qu'il a lancés.

(Je dois dire que j'ai volé ce code sur https://github.com/sequenceiq/hadoop-docker/blob/master/bootstrap.sh )


218

Cela a fait l'affaire pour moi:

docker run -dit ubuntu

Après cela, j'ai vérifié les processus en cours d'exécution en utilisant:

docker ps -a

Pour fixer à nouveau le conteneur

docker attach CONTAINER_NAME

CONSEIL: Pour quitter sans arrêter le type de conteneur: ^P^Q


15
@Tommy, from docs.docker.com/engine/reference/commandline/run -d, --detach Mode détaché: exécuter la commande en arrière-plan, -i, --interactive Garder STDIN ouvert même s'il n'est pas attaché, -t, - -tty Attribuer un pseudo-ATS -ditest juste un raccourci

3
@ am17torres à droite, désolé, permettez-moi de clarifier ma question confuse; d est détaché et i est interactif, donc la combinaison de d et i me porte à confusion. Je pensais que d devait le lancer en tant que processus d'arrière-plan (non interactif).
Tommy

2
@Tommy Lorsque ces options combinées, le conteneur entrera en mode interactif en arrière-plan .
Yon

2
@Tommy, @ am17torres -diest le minimum requis, l' -toption est redondante lorsqu'elle est utilisée avec -dsi je comprends bien
Renaud

2
En fait, vous ne pourrez pas voir votre invite si vous rattachez sans -tactivé ... mais puisque j'ai généralement execun nouveau bash chaque fois que je ne le remarque pas. J'ai eu des problèmes pour me détacher d'un Mac mais peut-être que je me trompe.
Renaud

65

Je voudrais étendre ou oserais-je dire, améliorer la réponse mentionnée par camposer

Quand tu cours

docker run -dit ubuntu

vous exécutez essentiellement le conteneur en arrière-plan en mode interactif.

Lorsque vous attachez et quittez le conteneur par CTRL + D (la façon la plus courante de le faire), vous arrêtez le conteneur parce que vous venez de tuer le processus principal qui a démarré votre conteneur avec la commande ci-dessus.

Profitant d'un conteneur déjà en cours d'exécution, je bifurquerais simplement un autre processus de bash et obtiendrais un pseudo TTY en exécutant:

docker exec -it <container ID> /bin/bash

29

chaque fois que je veux qu'un conteneur reste en place après avoir terminé l'exécution du script j'ajoute

&& tail -f /dev/null

en fin de commande. Il devrait donc être:

/usr/local/start-all.sh && tail -f /dev/null

19

Pourquoi le conteneur Docker se ferme immédiatement?

Si vous souhaitez forcer l'image à traîner (afin de déboguer quelque chose ou d'examiner l'état du système de fichiers), vous pouvez remplacer le point d'entrée pour le changer en shell:

docker run -it --entrypoint=/bin/bash myimagename

18

Une bonne approche serait de démarrer vos processus et services en les exécutant en arrière-plan et d'utiliser la wait [n ...]commande à la fin de votre script. En bash, la commande wait force le processus en cours à:

Attendez chaque processus spécifié et renvoyez son état de fin. Si n n'est pas donné, tous les processus enfants actuellement actifs sont attendus et l'état de retour est zéro.

J'ai eu cette idée dans le script de démarrage de Sébastien Pujadas pour sa construction d'élans .

Prenant la question d'origine, votre start-all.sh ressemblerait à quelque chose comme ça ...

 #!/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

5

Ajoutez ceci à la fin de Dockerfile:

CMD tail -f /dev/null

Exemple de fichier Docker:

FROM ubuntu:16.04

# other commands

CMD tail -f /dev/null

Référence


CMD tail -f /dev/nullle traverse sh -c "...". Pouvons-nous utiliser le execformulaire à la place? C'est à direCMD ["tail", "-f", "/dev/null"]
Meglio

4

Ma pratique est dans le Dockerfile démarrer un shell qui ne sortira pas immédiatement CMD [ "sh", "-c", "service ssh start; bash"], puis s'exécutera docker run -dit image_name. De cette façon, le service (ssh) et le conteneur sont en cours d'exécution.


1

J'ai ajouté une readdéclaration shell à la fin. Cela maintient le processus principal du conteneur - script shell de démarrage - en cours d'exécution.


1

Ajouter

exec "$@"

à la fin de mon script shell était ma solution!


Cela signifie simplement qu'il exécutera votre cmd, si votre cmd est juste 'bash' alors cela ne fonctionnera toujours pas
Shardj

1

Si vous vérifiez Dockerfile à partir de conteneurs, par exemple fballiano / magento2-apache-php

vous verrez qu'à la fin de son fichier, il ajoute la commande suivante: while true; dors 1; terminé

Maintenant, ce que je recommande, c'est que vous fassiez cela

docker container ls --all | grep 127

Ensuite, vous verrez si votre image docker avait une erreur, si elle se termine par 0, alors elle a probablement besoin d'une de ces commandes qui dormira pour toujours.


0

Il existe plusieurs façons de provoquer la fermeture immédiate d'un docker. Pour moi, c'était le problème avec mon Dockerfile. Il y avait un bogue dans ce fichier. J'avais ENTRYPOINT ["dotnet", "M4Movie_Api.dll]au lieu deENTRYPOINT ["dotnet", "M4Movie_Api.dll"] . Comme vous pouvez le voir, j'avais oublié une citation (") à la fin.

Pour analyser le problème, j'ai démarré mon conteneur et j'ai rapidement attaché mon conteneur afin que je puisse voir quel était le problème exact.

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


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

Où 4ea373efa21b est mon identifiant de conteneur. Cela m'amène au problème réel.

entrez la description de l'image ici

Après avoir trouvé le problème, j'ai dû créer, restaurer, publier à nouveau mon conteneur.


0

Venant de doublons, je ne vois aucune réponse ici qui traite de l'anti-modèle très courant consistant à exécuter votre charge de travail principale en tant que tâche d'arrière-plan, puis à vous demander pourquoi Docker se ferme.

En termes simples, si vous avez

my-main-thing &

puis retirez le &pour exécuter le travail au premier plan ou ajoutez

wait

à la fin du script pour le faire attendre tous les travaux en arrière-plan.

Il quittera alors toujours si la charge de travail principale se termine, alors peut-être l'exécuter en while trueboucle pour le forcer à redémarrer indéfiniment:

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

(Remarquez également comment écrire while true. Il est courant de voir des choses idiotes comme while [ true ]ou while [ 1 ]qui se produisent par hasard, mais ne signifient pas ce que l'auteur a probablement imaginé qu'elles devraient signifier.)


0

Vous devez l'exécuter avec l'indicateur -d pour le laisser s'exécuter en tant que démon en arrière-plan.

docker run -d -it ubuntu bash


-5

Vous pouvez exécuter le conteneur à l'aide de cet indicateur de redémarrage.

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

-8

Puisque l'image est un linux, une chose à vérifier est de s'assurer que tous les scripts shell utilisés dans le conteneur ont des fins de ligne unix. S'ils ont un ^ M à la fin, ce sont des fins de ligne Windows. Une façon de les corriger est d'utiliser dos2unix sur /usr/local/start-all.sh pour les convertir de Windows vers Unix. L'exécution du docker en mode interactif peut aider à résoudre d'autres problèmes. Vous pourriez avoir une faute de frappe ou quelque chose comme ça. voir https://en.wikipedia.org/wiki/Newline

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.