尝试从 docker 容器访问共享内存时出现“权限被拒绝”,即使 --ipc 设置为“主机”
Posted
技术标签:
【中文标题】尝试从 docker 容器访问共享内存时出现“权限被拒绝”,即使 --ipc 设置为“主机”【英文标题】:"Permission denied" when trying to access a shared memory from a docker container even though --ipc is set to "host" 【发布时间】:2020-09-17 13:08:00 【问题描述】:我正在尝试在我的主机中设置一个共享内存,并使用shmat
函数在centos:7
docker 容器中访问它。
我使用ipcmk -M 1024
创建了一个共享内存,并编写了一个ID 硬编码的C 程序(用于调试目的):
// shmtest.c
const char* shm_id = "98321";
shared_memory = shmat(atoi(shm_id), NULL, 0);
if (shared_memory == (void*)-1)
perror("No shared memory area");
abort();
fprintf(stdout, "Shared memory found!\n");
我的 Dockerfile 非常简单,我所做的只是复制编译后的程序并保持容器处于活动状态,以便我可以使用交互式 shell 对其进行检查:
# Dockerfile
FROM centos:7
COPY ./shmtest /root/
CMD tail -f /dev/null
我使用
构建和启动容器docker build -t shm-docker .
docker run --ipc="host" shm-docker
在 docker 容器中,我运行我的 shmtest
程序,但无法访问共享内存:
./shmtest
No shared memory area: Permission denied
Aborted
但是,ipcs
显示共享内存:
ipcs -m | grep 98321
0x8a39b8b3 98321 1000 644 65536 0
我试过了:
使用-v /dev/:/dev/
和 -v /dev/shm/:/dev/shm/
启动 docker 容器,没有任何运气
使用setcap
为我的程序提供CAP_IPC_OWNER 和CAP_IPC_LOCK 功能;然后我无法运行它 (./shmtest: Operation not permitted
)
在我的 Dockerfile 中用ubuntu:18.04
切换出centos:7
,仍然没有工作,这意味着这个问题不是特定于centos 的
不幸的是,我不太了解权限,但我注意到我的共享内存在运行ipcs
时显示数字644
,而其他各种显示600
。我也尝试过访问这些,但仍然遇到同样的错误。
我在这里缺少什么?我的想法是否有效,或者无法以这种方式访问共享内存?
【问题讨论】:
【参考方案1】:共享内存的权限644
允许其所有者读取和写入(前 6 个),但只授予其他所有人读取权限(后 4 个)。
docker 容器中的root
用户不是共享内存的所有者,因此他没有写入共享内存的权限。
如果您有权访问创建共享内存的工具,则可以将权限更改为 606
之类的内容,这意味着对所有者和其他所有人也有读写权限。例如,ipcmk
命令有一个-p
选项,因此您将运行ipcmk -M 1024 -p 0606
。
如果您无法更改共享内存的创建方式,可以通过将--privileged
标志或更准确地说,将--cap-add=IPC_OWNER
标志添加到docker run
命令来解决此问题。来自docker run reference:
当操作员执行 docker run --privileged 时,Docker 将启用对主机上所有设备的访问,并在 AppArmor 或 SELinux 中设置一些配置,以允许容器几乎与在容器外运行的进程一样访问主机在主机上。
除了 --privileged 之外,操作员还可以使用 --cap-add 和 --cap-drop 对功能进行细粒度控制。
关于IPC_OWNER
功能:
IPC_OWNER - 绕过对 System V IPC 对象的操作的权限检查。
现在是完整的命令
docker run --ipc="host" --privileged shm-docker
或
docker run --ipc="host" --cap-add=IPC_OWNER shm-docker
了解权限的好工具是Chmod Calculator,它是一个交互式工具,可以查看权限是如何以八进制数字和字符编码的。
【讨论】:
以上是关于尝试从 docker 容器访问共享内存时出现“权限被拒绝”,即使 --ipc 设置为“主机”的主要内容,如果未能解决你的问题,请参考以下文章
尝试从主机连接到 mysql docker 容器时出现“读取初始通信数据包”错误