在docker中访问主机目录时,权限被拒绝

简而言之:我试图在Docker中安装一个主机目录,但是我无法从容器中访问它,即使访问权限看起来不错。

细节:

我在做

sudo docker run -i -v /data1/Downloads:/Downloads ubuntu bash 

接着

 ls -al 

它给了我:

 total 8892 drwxr-xr-x. 23 root root 4096 Jun 18 14:34 . drwxr-xr-x. 23 root root 4096 Jun 18 14:34 .. -rwxr-xr-x. 1 root root 0 Jun 18 14:34 .dockerenv -rwx------. 1 root root 9014486 Jun 17 22:09 .dockerinit drwxrwxr-x. 18 1000 1000 12288 Jun 16 11:40 Downloads drwxr-xr-x. 2 root root 4096 Jan 29 18:10 bin drwxr-xr-x. 2 root root 4096 Apr 19 2012 boot drwxr-xr-x. 4 root root 340 Jun 18 14:34 dev drwxr-xr-x. 56 root root 4096 Jun 18 14:34 etc drwxr-xr-x. 2 root root 4096 Apr 19 2012 home 

还有更多的线条(我认为这是相关的部分)。

如果我做

 cd /Downloads ls 

结果是

 ls: cannot open directory .: Permission denied 

主机是Fedora 20,Docker 1.0.0和go1.2.2。

任何想法出了什么问题?

这是一个selinux问题。

你可以暂时问题

 su -c "setenforce 0" 

在主机上访问或者通过运行添加一个selinux规则

 chcon -Rt svirt_sandbox_file_t /path/to/volume 

关于Voumes和SELinux的完整案例,请看这个Project Atomic博客文章 。

特别:

最近Docker最终合并了一个将会在docker-1.7中显示的补丁(我们在docker-1.6上已经在RHEL,CentOS和Fedora上运行了这个补丁)。

此修补程序在卷挂载(-v)上添加对“z”和“Z”的支持作为选项。

例如:

 docker run -v /var/db:/var/db:z rhel7 /bin/sh 

将自动执行手册页中描述的chcon -Rt svirt_sandbox_file_t /var/db

更好的是,你可以使用Z.

 docker run -v /var/db:/var/db:Z rhel7 /bin/sh 

这将使用容器将运行的MCS标签来标记容器内的内容,基本上它会运行chcon -Rt svirt_sandbox_file_t -l s0:c1,c2 /var/db其中s0:c1,c2对于每个容器chcon -Rt svirt_sandbox_file_t -l s0:c1,c2 /var/db

尝试运行容器作为特权:

 sudo docker run --privileged=true -i -v /data1/Downloads:/Downloads ubuntu bash 

另一个选项(我没有尝试过)将创build一个特权的容器,然后在其中创build非特权的容器。

来自access.redhat.com:Sharing_Data_Across_Containers :

主机音量设置不可移植,因为它们是主机相关的,可能无法在任何其他机器上工作。 由于这个原因,没有将主机目录挂载到容器的Dockerfile等价物。 另外请注意,主机系统不知道容器的SELinux策略。 因此,如果强制执行SELinux策略,则无论rw设置如何,挂载的主机目录都不能写入容器。 目前,您可以通过将正确的SELinux策略types分配给主机目录来解决这个问题:

chcon -Rt svirt_sandbox_file_t host_dir

其中host_dir是安装到容器的主机系统上目录的path。

这似乎只是一个解决方法,但我试过,它的工作原理

我确认chcon -Rt svirt_sandbox_file_t /path/to/volume确实可以工作,而且不必作为特权容器运行。

这是:

  • Docker版本0.11.1-dev,build 02d20af / 0.11.1
  • centos7作为启用了selinux的主机和容器。

尝试docker volume create

 mkdir -p /data1/Downloads docker volume create --driver local --name hello --opt type=none --opt device=/data1/Downloads --opt o=uid=root,gid=root --opt o=bind docker run -i -v hello:/Downloads ubuntu bash 

看看文档https://docs.docker.com/engine/reference/commandline/volume_create/

我通过使用数据容器解决了这个问题,这也具有隔离数据与应用程序层的优点。 你可以像这样运行它:

 docker run --volumes-from=<container-data-name> ubuntu 

本教程对使用数据容器提供了一个很好的解释。