Чому я не можу використовувати Docker CMD кілька разів для запуску декількох служб?


96

Я створив базове зображення з Dockerfile на ім'я centos + ssh. У Dockerfile centos + ssh я використовую CMD для запуску служби ssh.

Тоді я хочу створити образ запуску іншої служби під назвою rabbitmq, Dockerfile:

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 сервіс не працює, сенс Dockerfile CMD Rabbitmq перекриває CMD центрів.

  1. Як CMD працює у зображенні докера?
  2. Якщо я хочу запустити кілька служб, як це зробити? Використовуєте супервізор?

Відповіді:


62

Незважаючи на те, що CMD записаний у Dockerfile, це дійсно інформація про час виконання. Так само, як EXPOSE, але всупереч, наприклад, RUN і ADD. Маючи на увазі, я маю на увазі, що ви можете переотримати його пізніше, в розширюваному Dockerfile, або просто в команді run, що саме ви відчуваєте. У будь-який час 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- спадщина /


Дякую, супервізор - це гарна ідея, але мені цікаво, як працює CMD всередині зображення
докера

2
Ви задали два запитання, 2. про використання декількох служб. Якщо вам цікаво, як працює CMD, будь ласка, детальніше розкажіть, що ви хочете знати конкретно. Я вже згадував, що це інформація про час роботи та перезапис будь-якою новою CMD.
qkrijger

118

Ви маєте рацію, другий файл Docker замінить CMDкоманду першого. Docker завжди буде виконувати одну команду, не більше. Отже, в кінці вашого 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

1
дякую, я думаю, що використання супервізора краще. але чому докер запускає лише один CMD? що відбувається всередині?
edwardsbean

1
Я не знаю, що відбувається всередині. Але я думаю, що це просто створено так. Коли у вас є зображення і виконується команда в ньому (наприклад, з CMD), він запускає контейнер. Контейнер працює до тих пір, поки виконується команда. І як тільки команда закінчується, контейнер також зупиняється. Отже кожен контейнер представляє одну єдину (запущену) команду.
Томас Угриг

я думаю, може, це через lcx або щось обмежене
edwardsbean

2
@ Tyguy7 .. тому що ................?
StartupGuy

1
&&техніка працюватиме лише з неінтерактивними службами (які можуть запускатися у фоновому режимі), інакше працює лише перший.
noraj

26

Хоча я поважаю відповідь qkrijger, що пояснює, як можна обійти цю проблему, я думаю, що ми можемо дізнатися більше про те, що відбувається тут ...

Насправді відповісти на ваше запитання " чому " ... Я думаю, що вам було б корисно зрозуміти, як docker stopпрацює команда, і що всі процеси повинні бути відключені чисто для запобігання проблем при спробі їх перезапустити (пошкодження файлів тощо).

Проблема: Що робити , якщо докер зробив запуск SSH від його команди і почав RabbitMQ з файлу Докер? " Команда докерної зупинки намагається спершу зупинити запущений контейнер шляхом надсилання сигналу SIGTERM кореневому процесу (PID 1) в контейнер. " Який процес відстежує докер як PID 1, який отримає SIGTERM? Це буде SSH чи Кролик ?? "Відповідно до моделі процесу Unix, процес init - PID 1 - успадковує всі діти-сироти і повинні їх повторно отримувати. Більшість контейнерів Docker не мають процесу init, який робить це правильно, і в результаті їх контейнери заповнюються зомбі-процеси з часом ".

Відповідь: Docker просто приймає , що останній CMD , як один , який буде запущений , як отримати кореневої процес з PID 1 та отримати SIGTERM від docker stop.

Пропоноване рішення: Вам слід використовувати (або створити) базове зображення, створене спеціально для роботи декількох служб, таких як phusion / baseimage

Слід зазначити, що tini існує саме з цієї причини, а станом на Docker 1.13 і вище, tini офіційно є частиною Докера, що говорить нам, що запуск декількох процесів у Docker ВЕРІТАЛЬНИЙ .. так що навіть якщо хтось претендує на бути більш кваліфікованим щодо Докера і наполягати на тому, що ви абсурдні, думаючи це робити, знайте, що не є. Для цього існують цілком слушні ситуації.

Добре знати:


3

Офіційна відповідь докера для запуску декількох служб у контейнері .

Він пояснює, як це можна зробити за допомогою системи init (systemd, sysvinit, upstart), script ( CMD ./my_wrapper_script.sh) або супервізора, як supervisord.

&&Обхідний шлях може працювати тільки за послуги , які починаються в фоновому режимі (демони) , або що буде швидко виконуватися без взаємодії і відпустіть запрошення. Зробити це за допомогою інтерактивного сервісу (який підтримує підказку), і тільки перша послуга запуститься.


0

Щоб вирішити, чому CMD призначений для запуску лише однієї служби на контейнер, давайте просто зрозуміємо, що буде, якщо вторинні сервери, що працюють в одному контейнері, не тривіальні / допоміжні, а "основні" (наприклад, сховище в комплекті з додатком frontend). Для початку це розбиває декілька важливих функцій контейнерації, таких як горизонтальне (автоматичне) масштабування та повторне планування між вузлами, обидва з яких припускають, що на контейнер є лише одна програма (джерело завантаження процесора). Потім виникає проблема вразливостей - більша кількість серверів, що перебувають у контейнері, означає частіші виправлення CVE ...

Тож давайте визнаємо, що це «підштовхування» дизайнерів Докера (та Kubernetes / Openshift) до передового досвіду, і ми не повинні винаходити обхідні шляхи (SSH не потрібен - ми docker exec / kubectl exec / oc rshрозробили його для заміни).

  • Більше інформації

/devops/447/why-it-is-recommended-to-run-only-one-process-in-a-container

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.