Почему я не могу использовать Docker CMD несколько раз для запуска нескольких сервисов?
Я создал базовое изображение из Dockerfile с именем centos + ssh. В файле centos + ssh Dockerfile я использую CMD для запуска службы ssh.
Затем я хочу создать образ, запускающий другую службу с именем rabbitmq, файл Docker:
FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD /opt/mq/sbin/rabbitmq-server start
Чтобы запустить контейнер rabbitmq, запустите:
docker run -d -p 222:22 -p 4149:4149 rabbitmq
но служба ssh не работает, это означает, что crbitmq Dockerfile CMD переопределяет centos CMD.
- Как CMD работает внутри изображения докеров?
- Если я хочу запустить несколько сервисов, как это сделать? Использование диспетчера?
Ответы
Ответ 1
Несмотря на то, что CMD записан в файле Docker, это действительно информация о времени выполнения. Так же, как EXPOSE, но, вопреки, например, RUN и ADD. Под этим я подразумеваю, что вы можете переопределить его позже, в расширении Dockerfile или просто в вашей команде запуска, что и есть то, что вы испытываете. Во все времена может быть только один CMD.
Если вы хотите запускать несколько служб, я бы использовал супервизор. Вы можете создать файл конфигурации супервизора для каждой службы, добавить их в каталог и запустить диспетчер с supervisord -c /etc/supervisor
, чтобы указать на файл конфигурации супервизора, который загружает все ваши службы и выглядит как
[supervisord]
nodaemon=true
[include]
files = /etc/supervisor/conf.d/*.conf
Если вы хотите получить более подробную информацию, я написал здесь блог на эту тему: http://blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image-inheritance/
Ответ 2
Вы правы, второй файл Docker будет перезаписывать команду CMD
первой. Докер всегда будет запускать одну команду, а не больше. Поэтому в конце вашего Dockerfile вы можете указать одну команду для запуска. Не более.
Но вы можете выполнять обе команды в одной строке:
FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD service sshd start && /opt/mq/sbin/rabbitmq-server start
Что вы могли бы сделать, чтобы сделать Dockerfile немного более чистым, вы могли бы поместить ваши команды CMD в дополнительный файл:
FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD sh /home/centos/all_your_commands.sh
И файл вроде этого:
service sshd start &
/opt/mq/sbin/rabbitmq-server start
Ответ 3
В то время как я уважаю ответ от qkrijger, объясняющий, как вы можете обойти эту проблему, я думаю, что мы можем многое узнать о том, что происходит здесь...
Чтобы ответить на ваш вопрос " почему"... Я думаю, вам было бы полезно понять, как работает команда docker stop
и что все процессы должны быть отключены, чтобы предотвратить проблемы когда вы пытаетесь перезапустить их (повреждение файлов и т.д.).
Проблема: что, если docker запустил SSH из этой команды и запустил RabbitMQ из вашего файла Docker? "Команда остановки docker пытается остановить запущенный контейнер сначала, отправив сигнал SIGTERM в корневой процесс (PID 1) в контейнере." Какой процесс отслеживается докерером как PID 1, который получит SIGTERM? Будет ли это SSH или кролик? "В соответствии с моделью процесса Unix процесс init - PID 1 - наследует все осиротевшие дочерние процессы и должен пожинать их. Большинство контейнеров Docker не имеют процесса инициализации, который делает это правильно, и в результате их контейнеры со временем заполняются зомбическими процессами" .
Ответ: Docker просто берет последний CMD как один, который будет запущен как корневой процесс с PID 1 и получит SIGTERM от docker stop
.
Предлагаемое решение: вы должны использовать (или создавать) базовое изображение, специально созданное для запуска более одной службы, например phusion/baseimage
Полезно знать: