我可以在Docker容器中运行多个程序吗?


150

从部署旨在在台式机上的用户上运行的应用程序的角度来看,我正在努力将自己的头全放在Docker上。我的应用程序只是一个Flask Web应用程序和mongo数据库。通常,我将同时安装在VM中,并将主机端口转发到来宾Web应用程序。我想尝试一下Docker,但不确定使用多个程序的含义。文档说只能有ENTRYPOINT,所以我如何拥有Mongo和我的flask应用程序。还是需要将它们放在单独的容器中,在这种情况下它们如何彼此通信,这如何使应用程序的分发变得容易?


2
现货上:让我想知道为什么泊坞窗是如此受欢迎。(单进程..?) -但让我们看看答案告诉我们。
javadba

Answers:


120

只能有一个ENTRYPOINT,但是该目标通常是一个脚本,该脚本启动所需的许多程序。您还可以使用例如Supervisord或类似工具来在单个容器内启动多个服务。这是一个在单个容器中运行mysql,apache和wordpress的docker容器的示例

假设您有一个供单个Web应用程序使用的数据库。然后,在单个容器中同时运行它们可能会更容易。

如果您有一个共享数据库供多个应用程序使用,则最好在其自己的容器中运行数据库,而每个应用程序都在各自的容器中运行。

当应用程序在不同的容器中运行时,它们至少有两种相互通信的可能性:

  1. 使用裸露的IP端口并通过它们进行连接。
  2. 最新的docker版本支持链接

1
看起来新版本的Docker现在支持Docker容器网络
jpierson

Docker现在支持运行Supervisor,允许您区分每个进程的行为,例如autorestart = true,stdout_logfile,stderr_logfile等。看看docs.docker.com/engine/admin/using_supervisord
Andreas Lundgren

4
在此示例中,我绝对不建议尝试在同一容器中运行Web应用程序和mongodb。在Docker中有监督或类似初始化过程的好用例,但这不是其中的一部分。使用docker-compose在单独的容器中运行两个服务更简单。
nicolas-van

@ nicolas-van为什么更简单?是因为如果数据库死亡,那么我可以重新启动数据库的容器,而不必重新启动整个容器?
brillout

同一台机器上的应用程序也可以通过Unix域套接字进行通信。保证最高性能。
怀疑儒勒

21

我对运行LAMP堆栈,Mongo DB和我自己的服务有类似的要求

Docker是基于OS的虚拟化,这就是为什么它在一个正在运行的进程中隔离其容器,因此它需要至少一个在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

这使我能够启动所有服务,并使容器保持活动状态,而最后一个服务开始处于前台

希望能帮助到你

UPDATE:自从我上次回答了这个问题,新的东西都拿出了像泊坞撰写,它可以帮助你在自己的容器中运行的每一项服务,但绑定所有的人都在一起,这些服务之间的依赖关系,试图更多地了解泊坞窗,撰写和使用它,除非您的需求不符合它,否则它是一种更优雅的方法。


6

我强烈不同意以前的一些建议在同一容器中运行两个服务的解决方案。文档中明确指出,不建议这样做

通常建议您通过每个容器使用一项服务来分离关注区域。该服务可以派生到多个进程中(例如,Apache Web服务器启动多个工作进程)。可以有多个进程,但是要从Docker中获得最大收益,请避免一个容器负责整个应用程序的多个方面。您可以使用用户定义的网络和共享卷连接多个容器。

有监督程序或类似程序的良好用例,但运行Web应用程序+数据库不属于其中。

您绝对应该使用docker-compose做到这一点,并编排具有不同职责的多个容器。


2
这是评论,不是答案。请考虑添加说明和/或链接以支持该职位。否则,它没有帮助。
伊万·伊万诺夫

1
从某种意义上来说,这是一个答案,我可以在这种用例中给出的最佳建议是使用docker-compose。无论如何,您是对的,我可以提供更多有关官方要求的链接。我会更新的。
nicolas-van,

问题是关于在一个容器中运行2个进程,因此不关心最佳实践。我将举一个例子:我也必须在基于PhotonOS的图像和Java进程中运行rabbitmq ...所以我使用了一个输入脚本,并用作ENTRYPOINT :)
Vallerious,

最初的问题不是关于在Docker容器中运行两个进程的技术可行性的通用问题。它陈述了一个特定的用例,即与MongoDB数据库一起部署Python应用程序。并且,对于该用例,最佳建议是不鼓励使用单个容器,并建议使用docker-compose。
nicolas-van

5

它们可以放在单独的容器中,实际上,如果应用程序也打算在更大的环境中运行,则可能会存在。

多容器系统将需要一些更多的业务流程,以便能够调出所有必需的依赖,但在泊坞v0.6.5 +,有一个新的设施与内置泊坞窗本身的帮助- 链接。对于多机解决方案,它仍然需要从Docker环境外部进行安排。

使用两个不同的容器,这两个部分仍通过TCP / IP进行通信,但是除非端口被专门锁定(不建议这样做,否则您将无法运行多个副本),则必须传递新端口数据库已经针对应用程序公开,因此它可以与Mongo通信。再次,链接可以提供帮助。

对于更简单的小型安装,其中所有依赖项都在同一个容器中进行,还可以通过最初称为ENTRYPOINT的程序来启动数据库和Python运行时。这可以简单的shell脚本,或其他一些过程控制器- Supervisord颇为流行,以及一些例子公共Dockerfiles存在。


3

我同意其他答案,即最好使用两个容器,但是如果您下定决心将多个服务捆绑在一个容器中,则可以使用supervisor之类的东西。

例如,在Hipache中,所包含的Dockerfile运行超级用户,而supervisord.conf文件则指定要运行的hipache和redis-server。


2

Docker提供了一些有关如何执行此操作的示例。轻量级的选项是:

将所有命令放入包装器脚本中,其中包含测试和调试信息。以您的身份运行包装脚本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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.