是否可以在Docker容器之间共享内存?

50

我正在开发一个涉及不同进程的应用程序,并被要求将这些进程进行隔离以实现更好的安全性。

问题在于,这些进程与单个“超级监控”进程共享内存以交换数据(它们使用经典的共享缓冲区)。这种解决方案是为了满足性能需求而实施的,因为它运行在用户空间中,所以不存在用户空间和内核空间之间的内容切换。

如果我没记错的话,不可能在单个IPC命名空间内运行多个docker容器,但我不知道是否可能让一个单独的docker容器属于不同的IPC命名空间,这可能可以解决我的问题。

其他解决方案也欢迎提供,但请记住性能是一项要求,谢谢。

4个回答

50

--ipc=host--ipc=container:id选项已经添加到Docker createrun命令中,用于共享IPC资源。

--ipc=""  : Set the IPC mode for the container,
             'container:<name|id>': reuses another container's IPC namespace
             'host': use the host's IPC namespace inside the container

与主机进行IPC通信

docker run --ipc=host <image>

与另一个容器进行IPC通信

docker run --ipc=container:<id> <image>

如果 dockerd 将 IPC 默认设置为 private,则与另一个容器进行 IPC 时可能需要在初始容器上设置 shareable 选项。

docker run --ipc=shareable <image>

16

从技术上讲,你可以在容器之间共享相同的IPC命名空间,但是Docker目前不支持这个功能。

如果你可以使用mmap()而非IPC,那么你可以在两个容器之间共享一个卷,并映射该卷上的文件;这将是同一个文件,因此可以正确共享。

如果你真的需要共享IPC命名空间(因为你无法更改现有代码),那就该编写一些Go代码并将其贡献给Docker :-)

最简单的方法可能是添加一个标志到libcontainer绑定中,以便你可以启动一个容器并重用主机(或另一个容器)的IPC命名空间。请检查--net标志的实现,因为它正是用于网络命名空间的。


1
我不知道这是否是一个真正的问题,但是使用tmpfs作为共享卷会减少任何不必要地刷新到磁盘的机会。 - twotwotwo
这是很好的信息。但是我如何验证它是否在幕后执行。我的意思是不刷新到磁盘。有什么想法吗? - Jairo Andres Velasco Romero
据我所知,这种情况下使用mmap()是不可能的。要想在IPC中使用mmap(),必须设置MAP_SHARED标志。但是该标志仅适用于从主进程派生出来的进程。 - Gabriel W.
1
只要映射文件,MAP_SHARED就可以在不相关的进程之间工作。 - jpetazzo

9
根据@jpetazzo的建议,我查看了Docker的源代码,并在#docker-dev的开发人员的帮助下成功地重新编译了Docker,以便放弃IPC命名空间。
要实现这一点,需要在文件default_template.go中注释掉"NEWIPC": true,行,该文件位于Docker源代码的docker/daemon/execdriver/native/template文件夹中。
旧代码现在运行得非常完美。

2
这里是它的工作方式:

使用可共享ipc启动容器

docker run -it --rm --ipc="shareable" --name cont1 ubuntu

然后开始下一个容器并与其IPC共享。保留HTML,不进行解释。
docker run -it --rm --name cont2 --ipc container:cont1 ubuntu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接