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

nic*_*ine 132 docker

我试图从部署一个旨在在桌面上运行的应用程序的角度来绕过Docker.我的应用程序只是一个烧瓶Web应用程序和mongo数据库.通常我会在VM中安装它们,并将主机端口转发到来宾Web应用程序.我想尝试一下Docker,但我不确定我打算如何使用多个程序.文件说只有ENTRYPOINT,所以我怎么能有Mongo和我的烧瓶申请.或者他们需要在单独的包含中,在这种情况下他们如何相互交谈以及这如何使分发应用程序变得容易?

小智 109

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

说,您有一个由单个Web应用程序使用的数据库.然后,在单个容器中运行它们可能更容易.

如果您有一个由多个应用程序使用的共享数据库,那么最好在自己的容器中运行数据库,并将每个应用程序放在各自的容器中.

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

  1. 使用暴露的IP端口并通过它们连接.
  2. 最近的docker版本支持链接.

  • 我绝对不会建议尝试在此示例中的同一容器中运行Web应用程序和mongodb.在Docker中有超级管理或类似init类似进程的良好用例,但这不是它们的一部分.使用docker-compose在单独的容器中运行两个服务更简单. (4认同)
  • 看起来新版本的 Docker 现在支持 [Docker 容器网络](https://docs.docker.com/engine/userguide/networking/dockernetworks/)。 (3认同)

Bas*_*sav 19

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

Docker是基于操作系统的虚拟化,这就是为什么它围绕正在运行的进程隔离其容器,因此它需要在FOREGROUND中运行至少一个进程.

因此,您提供自己的启动脚本作为入口点,因此您的启动脚本将成为扩展的Docker镜像脚本,在此脚本中您可以堆叠任意数量的服务,只要至少一个FOREGROUND服务已启动,即使是最终结束

所以我的Docker镜像文件在最后有两行:

COPY myStartupScript.sh /usr/local/myscripts/myStartupScript.sh
CMD ["/bin/bash", "/usr/local/myscripts/myStartupScript.sh"]
Run Code Online (Sandbox Code Playgroud)

在我的脚本中,我运行所有MySQL,MongoDB,Tomcat等.最后,我将Apache作为前台线程运行.

source /etc/apache2/envvars
/usr/sbin/apache2 -DFOREGROUND
Run Code Online (Sandbox Code Playgroud)

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

希望能帮助到你

更新:自从我上次回答这个问题以来,新的东西已经出现,比如Docker compose,它可以帮助你在自己的容器上运行每个服务,然后将所有这些服务绑定在一起作为这些服务之间的依赖关系,尝试了解更多有关docker-compose和使用它,它是更优雅的方式,除非你的需要与它不匹配.


nic*_*van 17

我强烈不同意之前的一些建议在同一个容器中运行这两个服务的解决方案。文档中明确指出它不是推荐的

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

supervisord 或类似程序有很好的用例,但运行 Web 应用程序 + 数据库不是其中的一部分。

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

  • 这是评论,而不是答案。请考虑添加解释和/或链接以支持此立场。否则是没有帮助的。 (5认同)
  • 这是一个答案,因为我在这种用例中可以给出的最佳建议是使用 docker-compose。无论如何,你是对的,我可以提供更多官方推荐的链接。我会更新的。 (5认同)
  • 问题是关于在一个容器中运行 2 个进程,因此不关心最佳实践。我会给你一个例子:我必须在基于 PhotonOS 的图像和 java 进程中运行rabbitmq...所以我使用了一个入口脚本并用作 ENTRYPOINT :) (2认同)
  • 这应该是答案。“我正在尝试了解 Docker”。显然,这是一个新的 Docker 用户,他不理解容器的概念,并试图将容器视为标准的 Web 服务器,许多 Docker 新手都曾经尝试过这样做(包括我自己) )。向用户指出文档并解释最佳实践是一个很好的答案。 (2认同)

Sam*_*Sam 8

You can run 2 processes in foreground by using wait. Just make a bash script with the following content. Eg start.sh:

# runs 2 commands simultaneously:

mongod & # your first application
P1=$!
python script.py & # your second application
P2=$!
wait $P1 $P2
Run Code Online (Sandbox Code Playgroud)

In your Dockerfile, start it with

CMD bash start.sh
Run Code Online (Sandbox Code Playgroud)


小智 6

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
Run Code Online (Sandbox Code Playgroud)

接下来是 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
Run Code Online (Sandbox Code Playgroud)


Ali*_*man 5

它们可以位于不同的容器中,实际上,如果应用程序也打算在更大的环境中运行,它们可能就是这样.

多容器系统需要更多的编排才能显示所有必需的依赖项,但在Docker v0.6.5 +中,有一个新的工具可以帮助构建Docker本身 - 链接.使用多机解决方案,它仍然需要从Docker环境外部进行安排.

使用两个不同的容器,这两个部分仍然通过TCP/IP进行通信,但除非端口已被特定锁定(不推荐,因为您无法运行多个副本),否则您必须通过新端口数据库已向应用程序公开,以便它可以与Mongo通信.这也是Linking可以提供帮助的东西.

对于更简单的小型安装,其中所有依赖项都在同一个容器中,同时也可以通过最初被称为ENTRYPOINT的程序启动数据库和Python运行时.这可以像shell脚本或其他一些过程控制器一样简单 - Supervisord非常流行,并且公共Dockerfiles中存在许多示例.