Подтвердить что ты не робот

Как сохранить работоспособность контейнера Docker после запуска сервисов?

Я видел кучу учебников, которые, похоже, делают то же самое, что я пытаюсь сделать, но почему-то мои контейнеры Docker выходят. В принципе, я настраиваю веб-сервер и несколько демонов внутри контейнера Docker. Я делаю последние части этого через bash script, называемый run-all.sh, который я запускаю через CMD в своем файле Docker. 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 script, чтобы сохранить его, но как правильно удержать его от выхода?

4b9b3361

Ответ 1

Это не так, как вы должны проектировать свои контейнеры Docker.

При разработке контейнера Docker вы должны его построить таким образом, чтобы выполнялся только один процесс (т.е. у вас должен быть один контейнер для Nginx, один для супервизора или приложения, в котором он работает); Кроме того, этот процесс должен работать на переднем плане.

Контейнер "выйдет", когда сам процесс завершится (в вашем случае этот процесс - ваш bash script).


Однако, если вам действительно нужно (или хотите) запустить несколько сервисов в контейнере Docker, подумайте, начиная с "Docker Base Image" , который использует runit как процесс псевдо-init (runit будет оставаться в сети, пока Nginx и Supervisor работают), который останется на переднем плане, пока ваши другие процессы выполняют свою задачу.

У них есть существенные документы, поэтому вы сможете достичь того, что вы пытаетесь сделать достаточно легко.

Ответ 2

Если вы используете файл Docker, попробуйте:

ENTRYPOINT ["tail", "-f", "/dev/null"]

(Очевидно, что это предназначено только для целей dev, вам не нужно сохранять контейнер в живых, если он не запускает процесс, например nginx...)

Ответ 3

У меня была такая же проблема, и я узнал, что если вы используете свой контейнер с флагом -t и -d, он продолжает работать.

docker run -td <image>

Вот что делают флаги (согласно docker run --help):

-d, --detach=false         Run container in background and print container ID
-t, --tty=false            Allocate a pseudo-TTY

Наиболее важным является флаг -t. -d просто позволяет запускать контейнер в фоновом режиме.

Ответ 4

Причина, по которой он выходит, заключается в том, что оболочка script запускается сначала как PID 1, и когда это завершено, PID 1 исчез, а докер работает только в то время, когда PID 1.

Вы можете использовать супервизор для выполнения всего, если он запускается с флагом "-n", который он сказал, чтобы не демонализовать, поэтому он останется первым процессом:

CMD ["/usr/bin/supervisord", "-n"]

И ваш supervisord.conf:

[supervisord]
nodaemon=true

[program:startup]
priority=1
command=/root/credentialize_and_run.sh
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=false
startsecs=0

[program:nginx]
priority=10
command=nginx -g "daemon off;"
stdout_logfile=/var/log/supervisor/nginx.log
stderr_logfile=/var/log/supervisor/nginx.log
autorestart=true

Затем вы можете иметь столько других процессов, сколько хотите, и диспетчер будет обрабатывать их перезапуск, если это необходимо.

Таким образом, вы можете использовать супервизор в случаях, когда вам понадобятся nginx и php5-fpm, и не имеет смысла их разлучать.

Ответ 5

Вы можете запустить обычный cat без каких-либо аргументов, как упомянуто bro @Sa'ad, чтобы просто поддерживать работу контейнера [фактически ничего не делая, кроме ожидания ввода данных пользователем) (плагин Jenkins 'Docker делает то же самое)

Ответ 6

Убедитесь, что вы добавили daemon off; к вам nginx.conf или запустили его с помощью CMD ["nginx", "-g", "daemon off;"] в соответствии с официальным изображением nginx

Затем используйте следующее, чтобы запустить как супервизор как службу, так и nginx в качестве процесса переднего плана, который предотвратит выход из контейнера

service supervisor start && nginx

В некоторых случаях вам нужно будет иметь более одного процесса в вашем контейнере, поэтому принудительное подключение контейнера к одному процессу не будет работать и может создать больше проблем при развертывании.

Итак, вам нужно понять компромиссы и принять ваше решение соответственно.

Ответ 7

Захват PID процесса ngnix в переменной (например, $NGNIX_PID) и в конце файла точки входа

wait $NGNIX_PID 

Таким образом, ваш контейнер должен работать до тех пор, пока ngnix не будет жив, когда ngnix остановится, контейнер также остановится

Ответ 8

Мотивация:

Нет ничего плохого в запуске нескольких процессов внутри контейнера Docker. Если вам нравится использовать докер в качестве легкоspring виртуальной машины - пусть будет так. Другие любят делить свои приложения на микро сервисы. Я думаю: ЛАМПА стек в одном контейнере? Просто здорово.

Ответ:

Придерживайтесь хорошего базового изображения, такого как базовое изображение. Там могут быть другие. Прокомментируйте, пожалуйста.

И это еще один призыв к руководителю. Потому что базовый образ phusion предоставляет супервизор помимо некоторых других вещей, таких как cron и locale setup. Вещи, которые вам нравятся, когда вы запускаете такую легкую виртуальную машину. Для чего это стоит и предоставляет ssh-соединения в контейнер.

Сам образ phusion просто запустится и продолжит работать, если вы выполните следующую базовую инструкцию запуска Docker:

[email protected]:~$ docker run -d phusion/baseimage
521e8a12f6ff844fb142d0e2587ed33cdc82b70aa64cce07ed6c0226d857b367
[email protected]:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS
521e8a12f6ff        phusion/baseimage   "/sbin/my_init"     12 seconds ago      Up 11 seconds

Или просто:

Если базовый образ не для вас... Для быстрой работы CMD я бы предположил что-то вроде этого для bash:

CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"

Или это для busybox:

CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"

Это хорошо, потому что он немедленно выйдет на docker stop. Простой sleep или cat займут несколько секунд, прежде чем контейнер выйдет.

Ответ 9

У меня такая же проблема. Вы можете попробовать эту команду: журналы докеров [контейнер]

Он покажет вам, почему контейнер останавливается. В моем случае он показывает: Разрешен отказ