为什么docker容器提示“Permission denied”?

新手上路,请多包涵

我使用以下命令运行 docker 容器,并将目录从主机( /root/database )映射到容器( /tmp/install/database ):

 # docker run -it --name oracle_install -v /root/database:/tmp/install/database bofm/oracle12c:preinstall bash

但是在容器中,我发现我无法使用 ls 列出 /tmp/install/database/ 中的内容,尽管我是 root 并且拥有所有权限:

 [root@77eb235aceac /]# cd /tmp/install/database/
[root@77eb235aceac database]# ls
ls: cannot open directory .: Permission denied
[root@77eb235aceac database]# id
uid=0(root) gid=0(root) groups=0(root)
[root@77eb235aceac database]# cd ..
[root@77eb235aceac install]# ls -alt
......
drwxr-xr-x. 7 root root  4096 Jul  7  2014 database

我在主机中检查 /root/database ,一切似乎都正常:

 [root@localhost ~]# ls -lt
......
drwxr-xr-x.  7 root root       4096 Jul  7  2014 database

为什么docker容器提示“Permission denied”?

更新

根本原因与 SELinux 有关。实际上,我去年遇到了类似的 问题

原文由 Nan Xiao 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.5k
2 个回答

在容器内拒绝共享目录的权限可能是因为该共享目录存储在设备上。默认情况下,容器不能访问任何设备。添加选项 $docker run --privileged 允许容器访问 所有 设备并执行内核调用。 这不被认为是安全的。

共享设备的一种更简洁的方法是使用选项 docker run --device=/dev/sdb (如果 /dev/sdb 是您要共享的设备)。

从手册页:

   --device=[]
      Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)

  --privileged=true|false
      Give extended privileges to this container. The default is false.

      By default, Docker containers are “unprivileged” (=false) and cannot, for example, run a Docker daemon inside the Docker container. This is because by default  a  container is not allowed to access any devices. A “privileged” container is given access to all devices.

      When  the  operator  executes  docker run --privileged, Docker will enable access to all devices on the host as well as set some configuration in AppArmor to allow the container nearly all the same access to the host as processes running outside of a container on the host.

原文由 Auzias 发布,翻译遵循 CC BY-SA 3.0 许可协议

我从以下评论中得到答案: 为什么 docker 容器提示权限被拒绝?

man docker-run 给出正确答案:

像 SELinux 这样的标签系统要求在安装到容器中的卷内容上放置适当的标签。如果没有标签,安全系统可能会阻止在容器内运行的进程使用内容。默认情况下,Docker 不会更改操作系统设置的标签。

要更改容器上下文中的标签,您可以将两个后缀 :z 或 :Z 添加到卷挂载中。这些后缀告诉 Docker 重新标记共享卷上的文件对象。 z 选项告诉 Docker 两个容器共享卷内容。因此,Docker 使用共享内容标签来标记内容。共享卷标允许所有容器读/写内容。 Z 选项告诉 Docker 使用私有非共享标签标记内容。只有当前容器可以使用私有卷。

例如:

   docker run -it --name oracle_install -v /root/database:/tmp/install/database:z ...

原文由 B.Z. 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题