Docker 卷挂载 NFS 共享的权限测试问题

Posted

技术标签:

【中文标题】Docker 卷挂载 NFS 共享的权限测试问题【英文标题】:Permissions tests issue with Docker volume mounting NFS share 【发布时间】:2021-10-03 06:41:41 【问题描述】:

我对以下 python 代码有疑问

import os
print("Can I write into the tv folder?",os.access("/tv", os.W_OK))
print("Does the /tv/test file exists?", os.access("/tv/test", os.R_OK))
with open("/tv/test", "w") as f:
    f.write("toto")
print("Does the /tv/test file exists now?", os.access("/tv/test", os.R_OK))
with open("/tv/test", "r") as f:
    print("Content of the /tv/test file:")
    print(f.read())

打印出来

Can I write into the tv folder? False
Does the /tv/test file exists? False
Does the /tv/test file exists now? True
Content of the /tv/test file;
toto

但根据第一次调用os.access,我应该无法编写测试文件...

我的问题不在于它已经能够创建文件,我想要那个。但是测试应该产生相关的结果。 (我使用的一个软件因此而出现故障)

我在树莓派上的 docker 容器(Docker 版本 20.10.7)中运行 Python 3.8.10,tv 文件夹是 docker 挂载的远程 nfs 共享。

root@7f0a44aad8a9:/> ls -la /tv
total 8
drwxrwxrwx 1 abc  abc   3826 Jul 27 14:18  .
drwxr-xr-x 1 root root  4096 Jul 27 14:12  ..
drwxrwxrwx 1 abc  abc    988 May 13 07:30 DARK
... (a lot of other folders)
-rwxrwxrwx 1 abc  abc      4 Jul 27 14:18  test

我的 docker-compose 文件:

version: "3.4"

services:
  bazarr:
    image: ghcr.io/linuxserver/bazarr
    container_name: bazarr
    volumes:
      - shows:/tv
    ports:
      - 6767:6767
    dns: 1.1.1.1
    restart: unless-stopped

volumes:
  shows:
    driver_opts:
      type: "nfs"
      o: "nfsvers=3,addr=xxx,soft,rw"
      device: ":xxx"

我知道os.access 可以给出假阳性,但可以给出假阴性? 有人看过这个吗? 这是意料之中的吗?

编辑:问题不是特定于 python 的

root@6c5dd99ee211:/> if [ -w /tv ]; then echo "WRITABLE"; else echo "NOT WRITABLE"; fi
NOT WRITABLE

但是为什么呢?

【问题讨论】:

可以ls -la /tv吗? 您是否确认您的问题实际上是 Python 代码而不是底层操作?比如test -w /tv在shell中成功了吗? 你是对的,test -w /tv 失败了。但为什么 ?因为我确实有权在里面创建文件。 【参考方案1】:

这与 POSIX 文件系统(包括 *nix 文件系统)的关系比与 Python 的关系更大。

但根据第一次调用os.access,我应该无法编写测试文件...

不,不幸的是这是错误的(但诚然有些不直观)。

在 POSIX 文件系统中,您可能没有写入目录的权限(这是您检查的内容),但这并不意味着您不能写入该目录中的文件。这意味着您不能将 new 文件写入所述目录。

例子:

(base) mmessersmith@HP-ZBK-0425:~$ mkdir test_dir
(base) mmessersmith@HP-ZBK-0425:~$ touch test_dir/abc.txt
(base) mmessersmith@HP-ZBK-0425:~$ cat test_dir/abc.txt
(base) mmessersmith@HP-ZBK-0425:~$ chmod 777 test_dir/abc.txt
(base) mmessersmith@HP-ZBK-0425:~$ chmod 500 test_dir
(base) mmessersmith@HP-ZBK-0425:~$ touch test_dir/new_file.txt
touch: cannot touch 'test_dir/new_file.txt': Permission denied
(base) mmessersmith@HP-ZBK-0425:~$ echo "123" > test_dir/abc.txt
(base) mmessersmith@HP-ZBK-0425:~$ cat test_dir/abc.txt
123
(base) mmessersmith@HP-ZBK-0425:~$ ls -al test_dir/
total 12
dr-x------  2 mmessersmith mmessersmith 4096 Jul 27 09:32 .
drwxr-xr-x 24 mmessersmith mmessersmith 4096 Jul 27 09:31 ..
-rwxrwxrwx  1 mmessersmith mmessersmith    4 Jul 27 09:32 abc.txt

请注意,我无法将新文件写入目录test_dir,但我仍然可以写入test_dir 内的abc.txt。在上面的示例中,您需要检查os.access("/tv/test", os.W_OK)。在我的 REPL 中,上面的例子:

(base) mmessersmith@HP-ZBK-0425:~$ python
Python 3.8.3 (default, May 19 2020, 18:47:26)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.access('test_dir', os.W_OK)
False
>>> os.access('test_dir/abc.txt', os.R_OK)
True
>>> os.access('test_dir/abc.txt', os.W_OK)
True

最后,请注意 os.access 是一个简单的 linux/unix 访问包装器:https://manpages.debian.org/buster/manpages-dev/access.2.en.html

所以不,这不是误报或误报,这只是文件系统的工作方式。

【讨论】:

对不起,由于重复测试我犯了一个错误。我可以在目录 tv 中创建一个新文件,这令人惊讶。对此感到抱歉 @pums974 在上面的示例中,您显示文件 已经 存在。例如你打电话给os.access("/tv/test", os.R_OK),它返回true。其次,os.access 是相对于调用的用户而言的。因此,如果您以自己的身份调用,但您的 docker 守护程序在 root 下运行,您一定会得到不同的结果。 从头开始,好像您刚刚将所说的调用更改为返回 false.... 是的,我在写问题并试图使其尽可能清晰时犯了错误。再次,我很抱歉。 似乎还有不止一个错误,b/c /tv 有 777 次烫发。请确保复制/粘贴准确您的情况......

以上是关于Docker 卷挂载 NFS 共享的权限测试问题的主要内容,如果未能解决你的问题,请参考以下文章

挂载nfs卷时如何解决postgresql docker容器的chown权限问题?

docker volume nfs 权限被拒绝

k8s文件挂载权限分析

docker-储存持久化

Docker Swarm - NFS 共享数据卷

docker挂载volume的用户权限问题,理解docker容器的uid