docker访问linux目录,在Docker中访问主机目录的权限被拒绝

通常,主机卷装入的权限问题是因为根据主机上文件的uid / gid权限,容器内的uid / gid无法访问该文件。但是,此特定情况不同。

权限字符串末尾的点drwxr-xr-x.表示已配置SELinux。与SELinux一起使用主机安装时,您需要在卷定义的末尾传递一个额外的选项:

该z选项指示绑定安装内容在多个容器之间共享。

该Z选项指示绑定安装内容是私有的且未共享。

您的volume mount命令将如下所示:

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

对于其他看到以其他用户身份运行容器的问题,您需要确保容器内用户的uid / gid有权访问主机上的文件。在生产服务器上,这通常是通过控制映像构建过程中的uid / gid来匹配具有访问文件权限的主机上的uid / gid来完成的(甚至更好的是,不要在生产环境中使用主机挂载)。

命名卷通常比主机挂载更可取,因为命名卷将从映像目录初始化卷目录,包括所有文件所有权和权限。当卷为空并且使用命名卷创建容器时,会发生这种情况。

MacOS用户现在拥有OSXFS,它可以在Mac主机和容器之间自动处理uid / gid。其中一个无济于事的地方是嵌入式VM内的文件已挂载到容器中,例如/var/lib/docker.sock。

对于每个开发人员可能更改主机uid / gid的开发环境,我的首选解决方案是使用以root身份运行的入口点启动容器,将用户的uid / gid固定在容器内以匹配主机卷uid / gid,并然后用于gosu从根目录降到容器用户以在容器内运行应用程序。重要的脚本fix-perms在我的基本图像脚本中,可以在以下位置找到:https : //github.com/sudo-bmitch/docker-base

该fix-perms脚本的重要部分是:

# update the uid

if [ -n "$opt_u" ]; then

OLD_UID=$(getent passwd "${opt_u}" | cut -f3 -d:)

NEW_UID=$(stat -c "%u" "$1")

if [ "$OLD_UID" != "$NEW_UID" ]; then

echo "Changing UID of $opt_u from $OLD_UID to $NEW_UID"

usermod -u "$NEW_UID" -o "$opt_u"

if [ -n "$opt_r" ]; then

find / -xdev -user "$OLD_UID" -exec chown -h "$opt_u" {} \;

fi

fi

fi

这样会将用户的uid和文件的uid放入容器内,如果不匹配,则调用usermod以调整uid。最后,它会进行递归查找以修复所有未更改uid的文件。我比使用带有-u $(id -u):$(id -g)标志的容器更好,因为上面的入口点代码不需要每个开发人员都运行脚本来启动容器,并且用户拥有的卷之外的任何文件都将得到其权限更正。

您还可以让docker通过使用执行绑定安装的命名卷从映像初始化主机目录。该目录必须预先存在,并且您需要提供主机目录的绝对路径,这与可能是相对路径的撰写文件中的主机卷不同。该目录也必须为空,以便docker对其进行初始化。定义绑定卷的命名卷的三个不同选项如下所示:

# create the volume in advance

$ docker volume create --driver local \

--opt type=none \

--opt device=/home/user/test \

--opt o=bind \

test_vol

# create on the fly with --mount

$ docker run -it --rm \

--mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \

foo

# inside a docker-compose file

...

volumes:

bind-test:

driver: local

driver_opts:

type: none

o: bind

device: /home/user/test

...

最后,如果您尝试使用用户名称空间,则会发现主机卷存在权限问题,因为容器的uid / gid已转移。在这种情况下,避免主机卷而仅使用命名卷可能是最容易的。

你可能感兴趣的:(docker访问linux目录)