为啥要构建多容器 docker 应用程序?

Posted

技术标签:

【中文标题】为啥要构建多容器 docker 应用程序?【英文标题】:Why multi-container docker apps are built?为什么要构建多容器 docker 应用程序? 【发布时间】:2021-05-11 23:09:06 【问题描述】:

有人可以用一些例子来解释吗?为什么要构建多容器 docker 应用程序?而您可以将您的应用程序包含在单个 docker 容器中。 当您制作多容器应用程序时,您必须进行网络连接。运行单个容器的单个镜像而不是两个容器的两个镜像不是很容易吗?

【问题讨论】:

应用程序的不同部分有不同的缩放需求。 你能用例子解释一下吗? 当你有多个独立的产品,需要在某个环境中运行时,让它们都在一个容器中运行是没有意义的。单点故障,它们都相互污染环境,没有隔离或简单的方法来监控它们。 也许稍后,但这里有一些值得深思的地方:如果您将数据库服务器(例如 postgres)与您的网络服务器放在同一个容器中,并且随着您的应用程序的增长,您会发现自己需要更多的网络服务器实例,你做什么?您是否从该图像中启动了更多容器?如果你这样做,数据库会发生什么? 【参考方案1】:

为了简化起见,我想说您只能在单个容器中运行一个具有公共入口点(如 API)的应用程序。其实这个方法是recommended by Docker official documentation。

微服务

由于这一单一约束,您无法在单个 Docker 容器中运行需要自己的入口点的微服务。 可以多讨论一下Monolith application vs Microservices的优势。

数据库

即使您决定只运行 Monolith 应用程序,您仍然需要在那里连接一些数据库。正如你所注意到的,Docker 有一个额外的网络配置层,所以如果你想在本地运行数据库和应用程序,最简单的方法是使用docker-compose 在一个自动配置的网络中运行两个镜像(数据库和你的应用程序)。

# Application definition
application: <your app definition>

# Database definition
database:
  image: mysql:5.7

在我的示例中,您可以通过主应用程序中的https://database:&lt;port&gt; URL(最终加上凭据)连接到您的数据库,它会起作用。

可扩展性

但是,为什么我们应该从应用程序中拆分数据库的图像?一个词 - 可扩展性。出于开发目的,您希望拥有本地数据库,也许使用 docker,因为它很方便。出于生产目的,您会将应用程序映像放在某个地方(Kubernetes、Docker-Swarm、Azure App Services 等)运行。要同时处理多个请求,您需要运行应用程序的多个实例。但是数据库呢?您无法连接到托管在同一容器中的数据库的内部实例,因为您的应用程序在其他容器中的其他实例将具有完全不同的数据集(没有同步)。 大多数情况下,您会选择使用单独的数据库服务器 - 无论是在容器上运行它还是在完全托管的数据库(如 Azure CosmosDB 或 Mongo Atlas)上运行它,但您自己的配置、缩放和同步专用于 DB。您的应用程序只需要担心正确的 URL。大多数云提供商都在开箱即用地公开此类服务,因此您不必担心自己的配置。

容易改变

最后但并非最不重要的争论是关于更改初始设置加班。您可能会更改数据库提供程序,或者将来升级映像的版本(这些事情是不时需要的)。当您分离图像时,您可以修改其中的一个而无需触及其他图像。它显着降低了维护成本。

此外,您可以非常轻松地添加其他服务 - 不同的日志聚合器?没问题,额外的微服务开箱即用?很简单。

【讨论】:

好的,但是为什么人们将他们的服务器端应用程序包含在两个容器中,即一个容器用于 DB,另一个容器用于其核心应用程序? 我用正确的解释更新了答案【参考方案2】:

这有几个很好的理由:

重用预建镜像更容易。如果您需要 MySQL、Redis 或 nginx 反向代理,这些都作为 Docker Hub 上的标准镜像存在,您可以将它们包含在一个 multi -容器 Docker Compose 设置。如果您尝试将它们放入单个映像中,则必须自己安装和配置它们。

Docker 工具是为单用途容器而构建的。 如果您想要多进程容器的日志,docker logs 通常会打印出supervisord 日志,这些日志不是你想要什么;如果您想重新启动其中一个容器,docker stop; docker rm; docker run 序列将删除整个内容。而对于多进程容器,您需要使用像 docker exec 这样的调试工具来做任何事情,这更难管理。

您可以升级一个部分而不影响其余部分。 升级容器中的代码通常涉及构建新映像、停止和删除旧容器以及从新映像运行新容器。 “删除旧容器”部分很重要,而且是例行公事;如果您需要删除数据库以升级应用程序,则可能会丢失数据。

您可以扩展一部分而不影响其余部分。更适用于 Docker Swarm 或 Kubernetes 等集群环境。如果您的应用程序过载(尤其是在生产中),您希望运行它的多个副本,但很难运行标准关系数据库的多个副本。这实际上需要您单独运行它们,因此您可以运行一个代理、五个应用程序服务器和一个数据库。

设置多容器应用程序应该不是特别困难;最简单的方法是使用 Docker Compose,它会为您处理诸如创建网络之类的事情。

【讨论】:

第二点看不懂。由于我们可以将数据保存在卷中,因此数据不会与图像一起被破坏。那么,删除一张图片有什么危险呢? 您可以在本地系统上模拟此工作流程。更改您的应用程序代码,将其保存在您的编辑器中,然后重新启动整个系统。没错,您可能不会丢失数据,但没有理由重新启动您没有更改的内容。

以上是关于为啥要构建多容器 docker 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

使用 docker buildx 构建多 CPU 架构镜像

docker镜像为啥有自己的ip

为啥“起航”命令没有构建我的 laravel docker 容器?

k8s和docker区别

为啥在 `npm install` 时`package-lock.json` 会导致 docker 容器构建失败?

数据在多容器 Dockerized 应用程序中的啥位置?