问题描述
我正在尝试在主机计算机中设置共享内存,并使用centos:7
函数在shmat
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("Can't access shared memory!");
abort();
}
fprintf(stdout,"Shared memory found!\n");
我的Dockerfile非常简单,我要做的就是复制编译后的程序并使容器保持活动状态,以便我可以使用交互式外壳对其进行检查:
# 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 -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
) - 使用
centos:7
切换Dockerfile中的ubuntu:18.04
仍然无法正常工作,这意味着此问题并非特定于centos
不幸的是,我对权限了解不多,但是我注意到我的共享内存在运行644
时显示数字ipcs
,而其他显示的则显示600
。我也尝试访问了这些内容,但仍然遇到相同的错误。
我在这里想念什么?我的想法是否有效,还是无法通过这种方式访问共享内存?
解决方法
共享内存的权限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是了解权限的一个很好的工具,它是一种交互式工具,也可以查看权限如何以八位数字和字符编码。