Могу ли я запускать несколько программ в контейнере Docker?

Я пытаюсь обернуть голову вокруг Docker с точки зрения развертывания приложения, которое предназначено для работы с пользователями на рабочем столе. Мое приложение - это просто флеш-приложение и база данных монго. Обычно я устанавливаю как в виртуальной машине, так и пересылаю порт хоста в гостевое веб-приложение. Я бы хотел попробовать Docker, но я не уверен, как я должен использовать более одной программы. В документах говорится, что может быть только ENTRYPOINT, так как я могу использовать приложение Mongo и my flask. Или они должны быть в отдельном содержимом, и в этом случае, как они общаются друг с другом и как это облегчает распространение приложения?

Ответ 1

Может быть только один ENTRYPOINT, но эта цель обычно представляет собой script, который запускает столько программ, которые необходимы. Вы можете дополнительно использовать, например, Supervisord или аналогично, чтобы позаботиться о запуске нескольких сервисов внутри одного контейнера. Это пример контейнера докеров, в котором запущены mysql, apache и wordpress в одном контейнере.

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

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

Существует как минимум две возможности взаимодействия друг с другом, когда они работают в разных контейнерах:

Ответ 2

У меня было похожее требование запуска стека LAMP, Mongo DB и моих собственных сервисов

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 и используйте его, это более элегантный способ, если ваши потребности не совпадают с ним.

Ответ 3

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

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

В двух разных контейнерах две части по-прежнему взаимодействуют через TCP/IP, но если только порты не были заблокированы специально (не рекомендуется, так как вы не смогли бы запустить более одной копии), вам придется пройти новый порт, который база данных была выставлена ​​в отношении приложения, чтобы он мог общаться с Mongo. Это опять-таки то, с чем может помочь Linking.

Для более простой и малой установки, где все зависимости находятся в одном и том же контейнере, также возможно использование как базы данных, так и среды выполнения Python, запущенной программой, которая изначально называется ENTRYPOINT. Это может быть так же просто, как оболочка script или какой-либо другой контроллер процесса - Supervisord довольно популярен, и существует ряд примеров в общедоступных Dockerfiles.

Ответ 4

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

Обычно рекомендуется разделять проблемные области, используя одну услугу на контейнер. Эта служба может разделяться на несколько процессов (например, веб-сервер Apache запускает несколько рабочих процессов). Можно использовать несколько процессов, но чтобы получить максимальную выгоду от Docker, избегайте того, чтобы один контейнер отвечал за множество аспектов вашего общего приложения. Вы можете подключить несколько контейнеров, используя пользовательские сети и общие тома.

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

Вы должны определенно использовать docker-compose для этого и организовать несколько контейнеров с разными обязанностями.

Ответ 5

Я согласен с другими ответами о том, что использование двух контейнеров предпочтительнее, но если вы настроены на создание нескольких сервисов в одном контейнере, вы можете использовать что-то вроде супервизора.

в Hipache, например, включенный Dockerfile запускает supervisord, а файл supervisord.conf указывает для запуска как hipache, так и redis-сервера.

Ответ 6

Docker предоставляет пару примеров о том, как это сделать. Легкий вариант:

Поместите все свои команды в оболочку script, в комплекте с тестированием и отладочную информацию. Запустите оболочку script как ваш CMD. Это очень наивный пример. Сначала обертка script:

#!/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

Далее, файл Docker:

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

Ответ 7

Вы можете запустить 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

Ответ 8

Если выделенный сценарий кажется чрезмерным, вы можете явным образом запускать отдельные процессы с помощью sh -c. Например:

CMD sh -c 'mini_httpd -C /my/config -D &' \
 && ./content_computing_loop