首页 > 解决方案 > Docker设计:容器之间交换数据还是将多个进程放在一个容器中?

问题描述

在当前项目中,我必须执行以下任务(除其他外):

目前,拼接和流在一个 docker 容器中运行,对象检测在另一个容器中运行,读取全景流作为输入。

由于我需要增加对象检测器的输入分辨率,同时保持 UI 的流分辨率,我必须寻找从拼接器容器中获取拼接(全分辨率)全景图(每帧约 10 MB)的替代方法检测器容器。

我对潜在解决方案的想法:

因为我不是 docker 抽屉里最锋利的刀,所以我要的是关于 docker 容器之间快速数据交换的提示、经验和最佳实践。

标签: dockerarchitecture

解决方案


通常 Docker 容器之间的大多数通信都是通过网络套接字进行的。当您与诸如关系数据库或 HTTP 服务器之类的东西交谈时,这很好。不过,听起来您的应用程序更多地是关于共享文件,而这正是 Docker 不太擅长的事情。

如果您只想要每个组件的一个副本,或者仍在积极开发管道:我可能不会为此使用 Docker。由于每个容器都有一个独立的文件系统和自己的用户 ID 空间,因此共享文件可能会非常棘手(每个容器必须就数字用户 ID 达成一致)。但是如果你只是在主机上运行所有东西,作为同一个用户,指向同一个目录,这不是问题。

如果你想在生产中扩展它:我会添加某种共享文件系统和像 RabbitMQ 这样的消息队列系统。对于本地工作,这可以是 Docker 命名卷或绑定挂载的主机目录;像 Amazon S3 这样的云存储也可以正常工作。设置是这样的:

  • 每个组件都知道共享存储并连接到 RabbitMQ,但不知道其他组件。
  • 每个组件从命名要处理的文件的 RabbitMQ 队列中读取消息。
  • 该组件读取文件并完成其工作。
  • 完成后,组件将结果文件写回共享存储,并将其位置写入 RabbitMQ 交换。

在此设置中,每个组件都是完全无状态的。例如,如果您发现其中的机器学习组件最慢,您可以运行它的副本。如果出现问题,RabbitMQ 会记住给定消息尚未完全处理(确认);再次由于隔离,您可以在本地运行该特定组件以重现和解决问题。

这个模型也可以很好地转化为更大规模的基于 Docker 的集群计算系统,比如 Kubernetes。

在本地运行它,我绝对会在单独的容器中保留单独的关注点(特别是如果单独的图像处理和 ML 任务很昂贵)。我建议的设置需要一个消息队列(用于跟踪工作)和一个共享文件系统(因为消息队列往往不会针对 10+ MB 的单个消息进行优化)。您可以在 Docker 命名卷和主机绑定挂载之间进行选择,作为现成的共享存储。绑定坐骑更容易检查和管理,但在某些平台上速度非常慢。我认为命名卷相当快,但您只能从 Docker 容器中访问它们,这意味着需要启动更多容器来执行备份和修剪等基本操作。


推荐阅读