Чи можна запускати кілька програм у контейнері Docker?


150

Я намагаюся обернути голову навколо Докера з точки розгортання програми, яка призначена для роботи над користувачами на робочому столі. Моя програма - це просто колбова веб-програма та база даних mongo. Зазвичай я б встановив і VM, і перенаправив хост-порт на гостьовий веб-додаток. Я хотів би спробувати Докера, але я не впевнений, як я маю на увазі використовувати більше однієї програми. У документації написано, що може бути лише ВПИС, тож як я можу мати монго та мою колбу. Або їм потрібно знаходитись в окремих контейнерах; в такому випадку як вони спілкуються один з одним і як це спрощує розповсюдження програми?


2
Місце на місці: змушує мене замислитися, чому докер був настільки популярний .. (єдиний процес ..?) - але давайте подивимося, що нам відповідають відповіді ..
javadba

Відповіді:


120

Тут може бути лише одна ENTRYPOINT, але цільовою ціллю зазвичай є сценарій, який запускає стільки програм, які потрібні. Ви можете додатково використовувати, наприклад, Supervisord або подібне, щоб подбати про запуск декількох служб всередині одного контейнера. Це приклад контейнера докера, який працює з mysql, apache та wordpress в одному контейнері .

Скажімо, у вас є одна база даних, яка використовується однією веб-програмою. Тоді, мабуть, простіше запустити обидва в одному контейнері.

Якщо у вас є спільна база даних, яка використовується більш ніж однією програмою, то краще буде запустити базу даних у власному контейнері, а додатки - у своїх контейнерах.

Існують щонайменше дві можливості, як програми можуть спілкуватися між собою, коли вони працюють у різних контейнерах:

  1. Використовуйте відкриті порти IP та підключайтесь через них.
  2. Останні версії докера підтримують посилання .

1
Схоже, нова версія Docker тепер підтримує контейнерні мережі Docker .
jpierson

Тепер Docker підтримує запуск Supervisor, що дозволяє вам відокремити поведінку для кожного процесу, такого як autorestart = true, stdout_logfile, stderr_logfile тощо. Погляньте на docs.docker.com/engine/admin/using_supervisord
Andreas Lundgren

4
Я б точно не рекомендував спробувати запустити веб-додаток і mongodb в одному контейнері в цьому прикладі. У Докері є добрі випадки спостереження або подібні процеси, подібні до init, але цей не є їх частиною. Простіше використовувати docker-compose, щоб просто запустити дві служби в окремі контейнери.
Ніколас-ван

@ nicolas-van чому це простіше? Це тому, що якщо db гине, я можу потім перезапустити контейнер db замість того, щоб перезавантажувати все це?
брильоут

Програми на одній машині також можуть спілкуватися через розетки домену Unix . Гарантована найвища продуктивність.
Скептичний Джул

21

У мене були подібні вимоги до запуску стека LAMP, DB Mongo та власних служб

Docker - це віртуалізація на базі ОС, саме тому вона ізолює свій контейнер навколо запущеного процесу, отже, йому потрібен хоча б один процес, запущений у FOREGROUND.

Таким чином, ви надаєте свій власний скрипт запуску як точку входу, таким чином ваш сценарій запуску стає розширеним скриптом зображення Docker, в якому ви можете складати будь-яку кількість служб настільки, наскільки ПОЧАТИ ОСТАННУ ВСЕГІДНУ ОБСЛУГОВУВАННЯ, ЯКІ ПЕРЕКЛЮЧИТИ ДО КІНЦЯ

Отже, мій файл зображень Docker має два рядки внизу в самому кінці:

COPY myStartupScript.sh /usr/local/myscripts/myStartupScript.sh
CMD ["/bin/bash", "/usr/local/myscripts/myStartupScript.sh"]

У моєму сценарії я запускаю всі MySQL, MongoDB, Tomcat тощо. Зрештою, я запускаю Apache як нитку переднього плану.

source /etc/apache2/envvars
/usr/sbin/apache2 -DFOREGROUND

Це дозволяє мені запустити всі свої послуги та підтримувати живий контейнер, коли останній сервіс почав бути на передньому плані

Сподіваюся, це допомагає

ОНОВЛЕННЯ : Оскільки я востаннє відповів на це запитання, з'явилися нові речі, як Docker compose , який може допомогти вам запустити кожну службу на своєму контейнері, але зв'язати їх усі як залежності між цими службами, спробуйте дізнатися більше про docker-compose і використовуйте його, це більш елегантний спосіб, якщо ваша потреба не відповідає йому.


6

Я категорично не згоден з деякими попередніми рішеннями, які рекомендували запускати обидві служби в одному контейнері. У документації чітко зазначено, що це не рекомендується :

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

Існують хороші випадки використання для контролю або подібних програм, але запуск веб-додатків + база даних не є їх частиною.

Ви обов'язково повинні використовувати docker-compose для цього та упорядкувати кілька контейнерів з різними обов'язками.


2
Це коментар, а не відповідь. Будь ласка, подумайте, щоб додати пояснення та / або посилання для підтримки цієї позиції. Інакше це не корисно.
Іван Іванов

1
Це відповідь у тому сенсі, що найкраща рекомендація, яку я можу дати в такому випадку використання, - це використовувати докер-композит. У будь-якому випадку ви маєте рацію, що я можу дати більше посилань на офіційні рекомендації. Я це оновлю.
nicolas-van

Питання стосується запуску 2 процесів в одному контейнері, таким чином, це не стосується кращих практик. Наведу приклад: мені довелося запускати rabbitmq всередині PhotonOS-зображення та ява-процесу ... Тому я використав сценарій входу та використовувався як ENTRYPOINT :)
Валентний

Оригінальне запитання не є загальним питанням щодо технічної доцільності запуску двох процесів у контейнері Docker. У ньому зазначено конкретний випадок використання - розгортання програми Python разом із базою даних MongoDB. І для цього випадку найкращою рекомендацією є відмовитися від використання одного контейнера та рекомендувати використовувати докер-композит.
Ніколас-ван

5

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

Система з декількома контейнерами потребує додаткової оркестрації, щоб мати змогу підняти всі необхідні залежності, хоча в Docker v0.6.5 + є новий інструмент, який допомагає вбудованому в сам Docker - Linking . Однак у мультимашинному рішенні все-таки щось доводиться влаштовувати поза середовищем Докера.

З двома різними контейнерами обидві частини все ще спілкуються через TCP / IP, але якщо порти не були заблоковані спеціально (не рекомендується, оскільки ви не зможете запустити більше однієї копії), вам доведеться пройти новий порт що база даних була піддана застосуванню, щоб вона могла спілкуватися з Монго. Це знову-таки, у чому може допомогти зв'язок.

Для більш простої невеликої установки, коли всі залежності перебувають в одному контейнері, і база даних, і час виконання Python, запущені програмою, яка спочатку називається ENTRYPOINT, також можлива. Це може бути таким же простим, як сценарій оболонки або якийсь інший контролер процесів - Supervisord є досить популярним, і в публічних Dockerfiles існує ряд прикладів.


3

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

в Hipache , наприклад, включений Dockerfile працює supervisord, а файл supervisord.conf визначає як для hipache і Redis-сервер для запуску.


2

Докер надає кілька прикладів, як це зробити. Легкий варіант:

Покладіть всі ваші команди в сценарій обгортки, доповнений тестуванням та налагодженням інформації. Запустіть сценарій обгортки як свій CMD. Це дуже наївний приклад. Спочатку сценарій обгортки:

#!/bin/bash

# Start the first process
./my_first_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_first_process: $status"
  exit $status
fi

# Start the second process
./my_second_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_second_process: $status"
  exit $status
fi

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container will exit with an error
# if it detects that either of the processes has exited.
# Otherwise it will loop forever, waking up every 60 seconds

while /bin/true; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they will exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit -1
  fi
  sleep 60
done

Далі, Dockerfile:

FROM ubuntu:latest
COPY my_first_process my_first_process
COPY my_second_process my_second_process
COPY my_wrapper_script.sh my_wrapper_script.sh
CMD ./my_wrapper_script.sh

2

За допомогою програми можна запустити 2 процеси на передньому плані wait. Просто зробіть сценарій bash із наступним змістом. Наприклад start.sh:

# runs 2 commands simultaneously:

mongod & # your first application
P1=$!
python script.py & # your second application
P2=$!
wait $P1 $P2

У своєму Dockerfile починайте його

CMD bash start.sh

0

Якщо виділений сценарій здається занадто великим накладними, ви можете нерегулярно породити окремі процеси sh -c. Наприклад:

CMD sh -c 'mini_httpd -C /my/config -D &' \
 && ./content_computing_loop
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.