J'ai vu un tas de tutoriels qui semblent faire la même chose que j'essaie de faire, mais pour une raison quelconque, mes conteneurs Docker se terminent. En gros, je mets en place un serveur Web et quelques démons dans un conteneur Docker. Je fais les dernières parties de cela via un script bash appelé run-all.sh
que je lance via CMD dans mon Dockerfile. run-all.sh
ressemble à ça:
service supervisor start
service nginx start
Et je le démarre dans mon Dockerfile comme suit:
CMD ["sh", "/root/credentialize_and_run.sh"]
Je peux voir que tous les services démarrent correctement lorsque j'exécute les choses manuellement (c'est-à-dire que je passe à l'image avec -i -t / bin / bash), et que tout semble fonctionner correctement lorsque j'exécute l'image, mais il se termine une fois il termine le démarrage de mes processus. J'aimerais que les processus s'exécutent indéfiniment, et pour autant que je sache, le conteneur doit continuer à fonctionner pour que cela se produise. Néanmoins, quand je cours docker ps -a
, je vois:
➜ 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
Ce qui donne? Pourquoi sort-il? Je sais que je pourrais simplement mettre une boucle while à la fin de mon script bash pour le maintenir, mais quelle est la bonne façon de l'empêcher de se terminer?
Réponses:
Ce n'est pas vraiment ainsi que vous devez concevoir vos conteneurs Docker.
Lors de la conception d'un conteneur Docker, vous êtes censé le construire de telle sorte qu'il n'y ait qu'un seul processus en cours d'exécution (c'est-à-dire que vous devriez avoir un conteneur pour Nginx et un pour le superviseur ou l'application qu'il exécute); en outre, ce processus doit s'exécuter au premier plan.
Le conteneur "quittera" lorsque le processus lui-même se terminera (dans votre cas, ce processus est votre script bash).
Cependant, si vous avez vraiment besoin (ou souhaitez) d'exécuter plusieurs services dans votre conteneur Docker, envisagez de commencer à partir de "Docker Base Image" , qui utilise
runit
comme processus pseudo-init (runit
restera en ligne pendant que Nginx et Supervisor s'exécutent), qui restera au premier plan pendant que vos autres processus font leur travail.Ils ont des documents importants, vous devriez donc être en mesure de réaliser ce que vous essayez de faire assez facilement.
la source
--nodaemon
option.Si vous utilisez un Dockerfile, essayez:
(Évidemment, c'est uniquement à des fins de développement, vous ne devriez pas avoir besoin de garder un conteneur en vie à moins qu'il n'exécute un processus, par exemple nginx ...)
la source
CMD["sleep", "1d"]
mais votre solution semble meilleureCMD["sleep", "infinity"]
.exec tail -f /dev/null
mais utilisertail
comme point d'entrée est une mauvaise réponse.J'ai juste eu le même problème et j'ai découvert que si vous exécutez votre conteneur avec le drapeau
-t
et-d
, il continue de fonctionner.Voici ce que font les drapeaux (selon
docker run --help
):Le plus important est le
-t
drapeau.-d
vous permet simplement d'exécuter le conteneur en arrière-plan.la source
docker logs <image>
pour m'assurer que c'était une erreur qui provoquait la fermeture de mon conteneur docker. L'état de sortie est0
et la dernière sortie est la confirmation que monlighttpd
serveur est en cours d'exécution:[ ok ] Starting web server: lighttpd.
exec bash
ouexec sh
si bash n'est pas installé, jusqu'à la fin de start.sh. Ensuite, vous pouvez utiliser l'indicateur -tLa raison pour laquelle il se ferme est que le script shell est d'abord exécuté en tant que PID 1 et qu'une fois terminé, le PID 1 a disparu et le docker ne s'exécute que pendant le PID 1.
Vous pouvez utiliser le superviseur pour tout faire, s'il est exécuté avec l'indicateur "-n", il est dit de ne pas démoniser, il restera donc le premier processus:
Et votre supervisord.conf:
Ensuite, vous pouvez avoir autant d'autres processus que vous le souhaitez et le superviseur se chargera de leur redémarrage si nécessaire.
De cette façon, vous pouvez utiliser supervisord dans les cas où vous pourriez avoir besoin de nginx et de php5-fpm et que cela n'a pas beaucoup de sens de les séparer.
la source
If the "init" process of a PID namespace terminates, the kernel terminates all of the processes in the namespace via a SIGKILL signal. This behavior reflects the fact that the "init" process is essential for the correct operation of a PID namespace.
vous pouvez exécuter plain
cat
sans aucun argument comme mentionné par bro @ Sa'ad pour simplement garder le conteneur en état de fonctionnement [en fait, en ne faisant rien d'autre qu'attendre l'entrée de l'utilisateur] (le plugin Docker de Jenkins fait la même chose)la source
cat
. le plugin docker de jenkin le fait.Assurez-vous que vous ajoutez
daemon off;
à vous nginx.conf ou exécutez-le avecCMD ["nginx", "-g", "daemon off;"]
selon l'image officielle nginxEnsuite, utilisez ce qui suit pour exécuter à la fois superviseur en tant que service et nginx en tant que processus de premier plan qui empêchera le conteneur de quitter
service supervisor start && nginx
Dans certains cas, vous devrez avoir plus d'un processus dans votre conteneur, donc forcer le conteneur à avoir exactement un processus ne fonctionnera pas et peut créer plus de problèmes de déploiement.
Vous devez donc comprendre les compromis et prendre votre décision en conséquence.
la source
Motivation:
Il n'y a rien de mal à exécuter plusieurs processus à l'intérieur d'un conteneur Docker . Si l'on aime utiliser docker comme machine virtuelle légère, qu'il en soit ainsi. D'autres aiment diviser leurs applications en micro-services. Je pense: Une pile de LAMP dans un conteneur? Tout simplement génial.
La réponse:
Tenez-vous en à une bonne image de base comme l' image de base de la phusion . Il peut y en avoir d'autres. Commentez s'il vous plaît.
Et ce n'est qu'un autre plaidoyer pour le superviseur. Parce que l'image de base de phusion fournit un superviseur en plus de certaines autres choses comme la configuration de cron et des paramètres régionaux. Les éléments que vous aimez configurer lors de l'exécution d'une machine virtuelle aussi légère. Pour ce que ça vaut, il fournit également des connexions ssh dans le conteneur.
L'image phusion elle-même démarrera et continuera à s'exécuter si vous émettez cette instruction d'exécution de base de docker:
Ou tout simplement:
Si une image de base n'est pas pour vous ... Pour que le CMD rapide le fasse fonctionner, je suppose que quelque chose comme ça pour bash:
Ou ceci pour busybox:
C'est bien, car il sortira immédiatement sur un fichier
docker stop
. Tout simplementsleep
oucat
prendra quelques secondes avant que le conteneur ne sorte.la source
Capturez le PID du processus ngnix dans une variable (par exemple $ NGNIX_PID) et à la fin du fichier entrypoint faire
De cette façon, votre conteneur doit s'exécuter jusqu'à ce que ngnix soit actif, lorsque ngnix s'arrête, le conteneur s'arrête également
la source
Que diriez-vous d'utiliser la forme de service de supervision si disponible?
service YOUR_SERVICE superviser
Vous évite d'avoir à créer un
supervisord.conf
la source