在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
本教程对使用数据容器提供了一个很好的解释。