【发布时间】:2015-08-12 15:16:37
【问题描述】:
我是否需要为我的复杂 Web 应用程序使用单独的 Docker 容器,或者我可以将所有必需的服务放在一个容器中?
当我能够在一个容器中安装和启动所有东西时,谁能解释我为什么要将我的应用程序划分为多个容器(例如 php-fpm 容器、mysql 容器、mongo 容器)?
【问题讨论】:
标签: docker architecture
我是否需要为我的复杂 Web 应用程序使用单独的 Docker 容器,或者我可以将所有必需的服务放在一个容器中?
当我能够在一个容器中安装和启动所有东西时,谁能解释我为什么要将我的应用程序划分为多个容器(例如 php-fpm 容器、mysql 容器、mongo 容器)?
【问题讨论】:
标签: docker architecture
有些人会告诉您每个容器只应运行 1 个进程。其他人会说每个容器 1 个应用程序。这些建议基于microservices 的原则。
我不认为微服务是适用于所有情况的正确解决方案,因此我不会仅仅因为这个原因而盲目地遵循这些建议。如果在一个容器中为您的案例有多个进程是有意义的,那么就这样做。 (请参阅Supervisor 和Phusion baseimage)
但分离容器还有另一个原因:在大多数情况下,您要做的工作更少。
在Docker Hub 上,有大量现成的 Docker 镜像。只需拉出您需要的即可。
接下来你要做的是:
docker-compose.yml 文件以方便操作这些容器【讨论】:
这取决于您对应用程序的愿景和路线图。在这种情况下,将应用程序的所有组件放在一个层中 docker 容器就像将所有鸡蛋放在一个篮子里一样。
每当您的应用程序需要安全性、性能相关问题时,将这三个组件分离到各自的容器中将是一个理想的解决方案。毋庸置疑,这种跨容器的分工会带来一定的成本,这与将这些容器连接在一起以进行通信和安全等有关。
【讨论】:
使用 Docker 时要考虑的是它在内部是如何工作的。 Docker 将您的 PID 1 替换为您在 Dockerfile 中的 CMD(和 ENTRYPOINT,稍微复杂一点)指令中指定的命令。 PID 1 通常是您的 init 系统所在的位置(sysvinit、runit、systemd 等)。无论从那里开始的任何过程,您的容器都会生死存亡。当进程终止时,您的容器就会终止。当您键入docker logs myContainer 时,容器中的标准输出和标准错误用于该进程 是您在主机上给出的。顺便说一句,这就是为什么您需要跳过障碍来启动服务并运行 cronjobs(通常由您的 init 系统完成的事情)。这对于理解以某种方式做事的动机非常重要。
现在,您可以为所欲为。关于执行此操作的“正确”方法有很多意见,但您可以扔掉所有这些并做您想做的事。因此,您可以弄清楚如何在一个容器中运行所有这些服务。但是现在您知道 docker 如何用您在 Dockerfiles 中的 CMD(和 ENTRYPOINT)中指定的任何命令替换 PID 1,您可能认为谨慎的做法是尝试让您的应用程序在各自的容器中运行,并让它们运行通过container linking 相互合作。 (更新 -- 2017 年 4 月 27 日:容器链接已被弃用,取而代之的是常规 ole container networking,后者更加健壮,其想法是您只需将单独的应用程序容器加入同一个网络以便他们可以互相交谈)。
如果您需要一些帮助来决定,我可以根据我自己的经验告诉您,当您将应用程序分成单独的容器然后将它们链接在一起时,它最终会变得更加简洁和易于维护。刚才我正在从 HHVM 构建一个 Wordpress 安装,我正在一个容器中安装 Nginx 和 HHVM/php-fpm,Wordpress 安装在另一个容器中,MariaDB 的东西在另一个容器中。将来,这将让我直接在我的 MariaDB 数据前面放置一个替换的 Wordpress 安装,几乎没有任何麻烦。对每个应用程序进行容器化是值得的。祝你好运!
【讨论】:
最好将您的 web 应用程序放在一个容器中,而将数据库等支持服务放在单独的容器中。通过这样做,如果您需要进行滚动更新或重新启动,您可以在应用程序节点进行单独重新启动时保持数据库在线,这样您就不会遇到停机时间。如果您使用 Redis 等进行缓存,出于同样的原因,这也很有用。它还将允许您更轻松地添加节点以以松散耦合的方式进行扩展。它还允许您以更适合特定目的的方式管理容器。对于您所描述的应用程序类型,我看到在单个容器上运行所有服务的论点很少。
【讨论】:
当您将 Web 应用程序划分为多个容器时,您无需在部署应用程序时重新启动所有服务。与传统一样,您在更新 Web 层时不会重新启动 mysql 服务器。
此外,如果您想扩展您的应用程序,将您的应用程序划分为单独的容器会更容易。然后,您可以扩展应用程序中解决瓶颈所需的那些部分。
【讨论】: