Я видел кучу учебников, которые, кажется, делают то же самое, что и я, но по какой-то причине мои контейнеры Docker закрываются. По сути, я настраиваю веб-сервер и несколько демонов внутри контейнера Docker. Я делаю последние части этого через скрипт bash, run-all.sh
который я запускаю через CMD в моем Dockerfile. run-all.sh
выглядит так:
service supervisor start
service nginx start
И я запускаю его внутри моего Dockerfile следующим образом:
CMD ["sh", "/root/credentialize_and_run.sh"]
Я вижу, что все службы запускаются правильно, когда я запускаю вещи вручную (то есть, получаю образ с помощью -i -t / bin / bash), и все выглядит так, как будто он работает правильно, когда я запускаю образ, но он выходит один раз это заканчивает запуск моих процессов. Я бы хотел, чтобы процессы выполнялись бесконечно, и, насколько я понимаю, контейнер должен продолжать работать, чтобы это произошло. Тем не менее, когда я бегу docker ps -a
, я вижу:
➜ 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
Что дает? Почему это выходит? Я знаю, что мог бы просто положить цикл while в конец моего bash-скрипта, чтобы он продолжался, но как правильно не допустить его выхода?
Ответы:
Это не совсем то, как вы должны проектировать свои контейнеры Docker.
При разработке контейнера Docker вы должны строить его так, чтобы выполнялся только один процесс (т. Е. У вас должен быть один контейнер для Nginx и один для супервизора или приложения, в котором он работает); Кроме того, этот процесс должен выполняться на переднем плане.
Контейнер будет «выходить» при выходе самого процесса (в вашем случае этот процесс является вашим bash-скриптом).
Однако, если вам действительно нужно (или вы хотите) запустить несколько служб в вашем контейнере Docker, рассмотрите возможность начать с «Базового образа Docker» , который использует
runit
в качестве процесса псевдо-инициализации (runit
будет оставаться в сети, пока запущены Nginx и Supervisor), который останется на переднем плане, в то время как другие ваши процессы делают свое дело.У них есть существенные документы, поэтому вы должны быть в состоянии достичь того, что вы пытаетесь сделать достаточно легко.
источник
--nodaemon
опции.Если вы используете Dockerfile, попробуйте:
(Очевидно, это только для целей разработки, вам не нужно сохранять контейнер живым, если он не запускает процесс, например. Nginx ...)
источник
CMD["sleep", "1d"]
но ваше решение кажется лучшеCMD["sleep", "infinity"]
.exec tail -f /dev/null
но использованиеtail
в качестве точки входа неверный ответ.Я просто была такая же проблема , и я обнаружил, что если вы используете свой контейнер с
-t
и-d
флагом, он продолжает работать.Вот что делают флаги (согласно
docker run --help
):Самый важный из них -
-t
флаг.-d
просто позволяет запустить контейнер в фоновом режиме.источник
docker logs <image>
чтобы убедиться, что это ошибка, которая приводит к выходу из моего док-контейнера. Статус выхода0
и последний вывод - подтверждение того, что мойlighttpd
сервер работает:[ ok ] Starting web server: lighttpd.
exec bash
или,exec sh
если bash не установлен, до конца start.sh. Тогда вы можете использовать флаг -tПричина, по которой он завершается, заключается в том, что сценарий оболочки запускается сначала как PID 1, а когда он завершен, PID 1 исчезает, а докер работает только тогда, когда PID 1 работает.
Вы можете использовать supervisor, чтобы делать все, если запускать с флагом "-n", ему запрещено не демонизироваться, поэтому он останется первым процессом:
И ваш supervisord.conf:
Тогда вы можете иметь столько других процессов, сколько захотите, и супервизор будет обрабатывать их перезапуск в случае необходимости.
Таким образом, вы можете использовать supervisord в тех случаях, когда вам могут понадобиться nginx и php5-fpm, и разбирать их не имеет особого смысла.
источник
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.
вы можете запустить обычный
cat
без каких-либо аргументов, как упомянуто bro @ Sa'ad, чтобы просто сохранить контейнер работающим [на самом деле ничего не делая, кроме ожидания пользовательского ввода] (плагин Jenkins 'Docker делает то же самое)источник
cat
. Докер плагин Дженкин делает это.Убедитесь, что вы добавляете
daemon off;
к себе nginx.conf или запускаете егоCMD ["nginx", "-g", "daemon off;"]
согласно официальному образу nginxЗатем используйте следующую команду для запуска супервизора как службы и nginx как процесса переднего плана, который будет препятствовать выходу контейнера
service supervisor start && nginx
В некоторых случаях вам понадобится иметь более одного процесса в вашем контейнере, поэтому принудительное использование в контейнере ровно одного процесса не будет работать и может создать больше проблем при развертывании.
Так что вам нужно понять компромиссы и принять соответствующее решение.
источник
Мотивация:
Нет ничего плохого в запуске нескольких процессов внутри контейнера Docker . Если вам нравится использовать докер в качестве легковесной виртуальной машины - пусть будет так. Другие любят делить свои приложения на микро сервисы. Я думаю: ЛАМПА стек в одном контейнере? Просто прекрасно.
Ответ:
Придерживайтесь хорошего базового изображения, такого как базовое изображение . Там могут быть другие. Пожалуйста, прокомментируйте.
И это еще одна просьба к руководителю. Потому что базовый образ phusion предоставляет супервизор помимо некоторых других вещей, таких как cron и locale setup. Вещи, которые вы хотели бы настроить при работе с такой легкой виртуальной машиной. Для чего это стоит также предоставляет ssh-соединения в контейнер.
Сам образ phusion просто запустится и продолжит работу, если вы выполните следующую базовую инструкцию запуска Docker:
Или просто:
Если базовый образ не для вас ... Для быстрой работы CMD я бы предположил что-то вроде этого для bash:
Или это для busybox:
Это хорошо, потому что он сразу выйдет на
docker stop
. Простоsleep
илиcat
займет несколько секунд, прежде чем контейнер выйдет.источник
Захват PID процесса ngnix в переменной (например, $ NGNIX_PID) и в конце файла точки входа выполните
Таким образом, ваш контейнер должен работать, пока ngnix не будет активен, когда ngnix останавливается, контейнер также останавливается
источник
Как насчет использования формы обслуживания, если таковая имеется?
Сервис YOUR_SERVICE контролирует
Спасает необходимость создания
supervisord.conf
источник