我使用以下命令运行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
有关。实际上,去年我遇到了类似的issue。
答案 0 :(得分:5)
容器内针对共享目录拒绝的权限可能是由于此共享目录存储在设备上。默认情况下,容器无法访问任何设备。添加选项$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.
答案 1 :(得分:1)
我从以下评论中得到答案:Why does docker container prompt Permission denied?
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 ...
答案 2 :(得分:0)
使用docker-compose将nfs挂载点作为卷共享时,我遇到了类似的问题。我能够通过以下方式解决问题:
docker-compose up --force-recreate
尽管你发现了这个问题,但这可能有助于其他人。
答案 3 :(得分:0)
另一个原因是与UID / GID不匹配。这通常表现为能够以root身份修改挂载而不是容器用户
您可以设置UID,因此对于以ubuntu身份运行的ubuntu容器,您可能需要附加:uid=1000
(请查看id -u
)或根据您的使用情况在本地设置UID。
uid = value和gid = value
设置文件系统中文件的所有者和组(默认值:uid = gid = 0)
这里有一个很好的博客,关于这个tmpfs示例
docker run \
--rm \
--read-only \
--tmpfs=/var/run/prosody:uid=100 \
-it learning/tmpfs