Docker 实战:共享内存命名空间

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

在这篇摘自 《Docker in Action》 一书的文章中,我将向您展示如何在容器之间打开对共享内存的访问。

Linux 提供了一些工具用于在同一台计算机上运行的进程之间共享内存。这种形式的进程间通信 (IPC) 以内存速度执行。当与基于网络或管道的 IPC 相关的延迟拖累软件性能低于要求时,通常会使用它。基于共享内存的 IPC 使用的最佳示例是科学计算和一些流行的数据库技术,如 PostgreSQL。

Docker 默认为每个容器创建一个唯一的 IPC 命名空间。 Linux IPC 命名空间对共享内存原语(如命名共享内存块和信号量)以及消息队列进行分区。如果您不确定这些是什么也没关系。只知道它们是 Linux 程序用来协调处理的工具。 IPC 命名空间可防止一个容器中的进程访问主机或其他容器中的内存。

在容器之间共享 IPC 原语

我创建了一个名为 allingeek/ch6_ipc 的图像,其中包含生产者和消费者。他们使用共享内存进行通信。清单 1 将帮助您理解在单独的容器中运行它们的问题。

清单 1:启动一对通信程序


 # start a producer
docker -d -u nobody --name ch6_ipc_producer \  
  allingeek/ch6_ipc -producer 

start the consumer

docker -d -u nobody --name ch6_ipc_consumer \
allingeek/ch6_ipc -consumer

清单 1 启动了两个容器。第一个创建消息队列并开始在其上广播消息。第二个应该从消息队列中拉出并将消息写入日志。您可以使用以下命令检查每个日志来查看每个日志在做什么:


 # start a producer
docker -d -u nobody --name ch6_ipc_producer \  
  allingeek/ch6_ipc -producer 

start the consumer

docker -d -u nobody --name ch6_ipc_consumer \
allingeek/ch6_ipc -consumer


如果您执行清单 1 中的命令,应该会出现错误。消费者永远不会在队列中看到任何消息。每个进程使用相同的密钥来标识共享内存资源,但它们引用不同的内存。原因是每个容器都有自己的共享内存命名空间。

如果您需要运行与不同容器中的共享内存通信的程序,那么您将需要使用 --ipc 标志加入它们的 IPC 命名空间。 --ipc 标志有一个容器模式,它将在与另一个目标容器相同的 IPC 命名空间中创建一个新容器。

清单 2:加入共享内存命名空间


 # start a producer
docker -d -u nobody --name ch6_ipc_producer \  
  allingeek/ch6_ipc -producer 

start the consumer

docker -d -u nobody --name ch6_ipc_consumer \
allingeek/ch6_ipc -consumer


清单 2 重建消费者容器并重用 ch6_ipc_producer 容器的 IPC 名称空间。这次消费者应该能够访问服务器正在写入的相同内存位置。您可以通过使用以下命令检查每个日志来查看此工作:


 # start a producer
docker -d -u nobody --name ch6_ipc_producer \  
  allingeek/ch6_ipc -producer 

start the consumer

docker -d -u nobody --name ch6_ipc_consumer \
allingeek/ch6_ipc -consumer

请记住在继续之前清理正在运行的容器:


 # start a producer
docker -d -u nobody --name ch6_ipc_producer \  
  allingeek/ch6_ipc -producer 

start the consumer

docker -d -u nobody --name ch6_ipc_consumer \
allingeek/ch6_ipc -consumer

重用容器的共享内存命名空间有明显的安全隐患。但如果您需要,此选项可用。在容器之间共享内存比与主机共享内存更安全。