为什么要构建多容器 docker 应用程序?
Why multi-container docker apps are built?
有人可以举例说明吗?为什么要构建多容器 docker 应用程序?而您可以将您的应用包含在单个 docker 容器中。
当您制作多容器应用程序时,您必须进行联网。 运行 单个容器的单个图像而不是两个容器的两个图像不是很容易吗?
为了简单起见,我会说在一个容器中您只能 运行 一个具有 public 入口点(如 API)的应用程序。其实这个做法就是recommended by Docker official documentation.
微服务
由于这个单一的约束,您不能 运行 在单个 docker 容器中需要自己的入口点的微服务。
它可能更多地讨论 .
的优点
数据库
即使您决定 运行 仅使用 Monolith 应用程序,您仍然需要在那里连接一些数据库。正如您所注意到的,Docker 有一个额外的网络配置层,所以如果您想在本地 运行 数据库和应用程序,最简单的方法是同时使用 docker-compose 和 运行图像(数据库和您的应用程序)在一个自动配置的网络中。
# Application definition
application: <your app definition>
# Database definition
database:
image: mysql:5.7
在我的示例中,您只需通过 https://database:<port>
URL 从您的主应用程序(最终加上凭据)连接到您的数据库即可。
可扩展性
但是,为什么我们要从应用程序中拆分数据库的图像?一个词 - 可扩展性。出于开发目的,您希望拥有本地数据库,也许 docker 因为它很方便。出于生产目的,您会将应用程序映像放在 运行 某个地方(Kubernetes、Docker-Swarm、Azure App Services 等)。要同时处理多个请求,您需要 运行 应用程序的多个实例。但是数据库呢?您无法连接到同一容器中托管的数据库的内部实例,因为其他容器中的应用程序的其他实例将具有完全不同的数据集(没有同步)。
大多数情况下,您会选择使用单独的数据库服务器——无论 运行 将其放在容器或完全托管的数据库(如 Azure CosmosDB 或 Mongo Atlas)上,但使用您自己的配置、缩放、和同步专用于数据库。您的应用程序只需要担心正确的 URL 即可。大多数云提供商都开箱即用地公开此类服务,因此您不必担心自己的配置。
易于更改
最后但并非最不重要的争论是关于超时更改初始设置。您可能会更改数据库提供程序,或者将来升级图像的版本(有时需要这样的事情)。当您分离图像时,您可以在不接触其他图像的情况下修改一个图像。它显着降低了维护成本。
此外,您可以非常轻松地添加其他服务 - 不同的日志聚合器?没问题,额外的微服务 运行 开箱即用?简单。
这有几个很好的理由:
重用预建镜像更容易。如果你需要MySQL,或者Redis,或者Nginx反向代理,这些都作为标准镜像存在于Docker Hub,您可以将它们包含在多容器中 Docker Compose 设置。如果您尝试将它们放入单个映像中,则必须自己安装和配置它们。
Docker工具是为单用途容器构建的。如果你想要多进程容器的日志,docker logs
通常会打印输出 supervisord
日志,这不是您想要的;如果你想重新启动其中一个容器,docker stop; docker rm; docker run
序列将删除整个容器。取而代之的是多进程容器,你需要使用像 docker exec
这样的调试工具来做任何事情,这更难管理。
你可以升级一个部分而不影响其余部分。 升级容器中的代码通常涉及构建新镜像、停止和删除旧容器以及运行从新图像中创建一个新容器。 “删除旧容器”部分很重要,也是例行公事;如果您需要删除数据库来升级您的应用程序,您可能会丢失数据。
您可以扩展一部分而不影响其余部分。更适用于 Docker Swarm 或 Kubernetes 等集群环境。如果您的应用程序过载(尤其是在生产中),您希望 运行 它的多个副本,但很难 运行 标准关系数据库的多个副本。这基本上需要您分别 运行 这些,因此您可以 运行 一个代理、五个应用程序服务器和一个数据库。
设置多容器应用程序应该不是特别困难;最简单的方法是使用 Docker Compose,它将处理诸如为您创建网络之类的事情。
有人可以举例说明吗?为什么要构建多容器 docker 应用程序?而您可以将您的应用包含在单个 docker 容器中。 当您制作多容器应用程序时,您必须进行联网。 运行 单个容器的单个图像而不是两个容器的两个图像不是很容易吗?
为了简单起见,我会说在一个容器中您只能 运行 一个具有 public 入口点(如 API)的应用程序。其实这个做法就是recommended by Docker official documentation.
微服务
由于这个单一的约束,您不能 运行 在单个 docker 容器中需要自己的入口点的微服务。
它可能更多地讨论
数据库
即使您决定 运行 仅使用 Monolith 应用程序,您仍然需要在那里连接一些数据库。正如您所注意到的,Docker 有一个额外的网络配置层,所以如果您想在本地 运行 数据库和应用程序,最简单的方法是同时使用 docker-compose 和 运行图像(数据库和您的应用程序)在一个自动配置的网络中。
# Application definition
application: <your app definition>
# Database definition
database:
image: mysql:5.7
在我的示例中,您只需通过 https://database:<port>
URL 从您的主应用程序(最终加上凭据)连接到您的数据库即可。
可扩展性
但是,为什么我们要从应用程序中拆分数据库的图像?一个词 - 可扩展性。出于开发目的,您希望拥有本地数据库,也许 docker 因为它很方便。出于生产目的,您会将应用程序映像放在 运行 某个地方(Kubernetes、Docker-Swarm、Azure App Services 等)。要同时处理多个请求,您需要 运行 应用程序的多个实例。但是数据库呢?您无法连接到同一容器中托管的数据库的内部实例,因为其他容器中的应用程序的其他实例将具有完全不同的数据集(没有同步)。
易于更改
最后但并非最不重要的争论是关于超时更改初始设置。您可能会更改数据库提供程序,或者将来升级图像的版本(有时需要这样的事情)。当您分离图像时,您可以在不接触其他图像的情况下修改一个图像。它显着降低了维护成本。
此外,您可以非常轻松地添加其他服务 - 不同的日志聚合器?没问题,额外的微服务 运行 开箱即用?简单。
这有几个很好的理由:
重用预建镜像更容易。如果你需要MySQL,或者Redis,或者Nginx反向代理,这些都作为标准镜像存在于Docker Hub,您可以将它们包含在多容器中 Docker Compose 设置。如果您尝试将它们放入单个映像中,则必须自己安装和配置它们。
Docker工具是为单用途容器构建的。如果你想要多进程容器的日志,docker logs
通常会打印输出 supervisord
日志,这不是您想要的;如果你想重新启动其中一个容器,docker stop; docker rm; docker run
序列将删除整个容器。取而代之的是多进程容器,你需要使用像 docker exec
这样的调试工具来做任何事情,这更难管理。
你可以升级一个部分而不影响其余部分。 升级容器中的代码通常涉及构建新镜像、停止和删除旧容器以及运行从新图像中创建一个新容器。 “删除旧容器”部分很重要,也是例行公事;如果您需要删除数据库来升级您的应用程序,您可能会丢失数据。
您可以扩展一部分而不影响其余部分。更适用于 Docker Swarm 或 Kubernetes 等集群环境。如果您的应用程序过载(尤其是在生产中),您希望 运行 它的多个副本,但很难 运行 标准关系数据库的多个副本。这基本上需要您分别 运行 这些,因此您可以 运行 一个代理、五个应用程序服务器和一个数据库。
设置多容器应用程序应该不是特别困难;最简单的方法是使用 Docker Compose,它将处理诸如为您创建网络之类的事情。