Docker数据卷:使用挂载选项指定权限

18

我正在尝试使用一个在Docker容器中挂载的命名卷,但当我尝试在挂载的文件夹创建文件时出现“权限被拒绝”的错误。因此,我正在尝试在创建我的卷时使用mount选项,但那并不像我想要的那样起作用。

介绍

我完全知道当使用docker volume create my_named_volume创建一个卷,并使用选项 -v my_named_volume:/home/user/test 或者 --mount type=volume,source=my_named_volume,target=/home/user/test 来挂载它时,容器内部的文件夹(/home/user/test)将由root用户拥有,即使/home/user属于我在Dockerfile中创建的一个名为user的用户。如果我运行:

docker run --rm \
    --name test_named_volume \
    --mount type=volume,source=my_named_volume,target=/home/user/test \
    test_named_volume \
    su user -c "touch /home/user/test/a"

然后我得到:

touch: cannot touch '/home/user/test/a': Permission denied

我理解这一点。这就是为什么在创建我的卷时,我尝试使用mount选项的原因。

mount选项

我正在创建我的卷时指定uid,以便让我的用户user能够在该卷中创建文件:

docker volume create my_named_volume \
    --opt o=uid=1000

1000是我在Dockerfile中创建的useruid


FROM    debian:jessie

ENV     HOME /home/user

RUN     useradd \
            --create-home \
            --home-dir $HOME \
            --uid 1000 \
            user \
 &&     chown -R user:user $HOME

WORKDIR $HOME

但是当我运行我的容器(使用上面定义的相同命令docker run)时,出现了一个错误(missing device in volume options):

docker: Error response from daemon: error while mounting volume '/var/lib/docker/volumes/my_named_volume/_data': missing device in volume options.

文档中,我发现我的卷创建选项--device--type已经不见了:

docker volume create my_named_volume \
    --opt device=??? \
    --opt type=??? \
    --opt o=uid=1000

但我不明白为什么我必须提供这些选项。 device 需要是一个块设备,从我所读到的,type 应该是类似 ext4 的东西。但我的目的基本上就是将 uid 选项设置为我的卷。看起来创建一个块设备应该可以解决问题,但对于一个“简单”的问题来说,它似乎过于复杂。

我尝试使用 tmpfs 作为 devicetype,这很好用(文件 /home/user/test/a 被创建了)... 直到我的容器停止(数据没有被保留,这很合理因为它是 tmpfs)。我希望退出容器后卷中写入的数据可以持久化。

在容器中挂载命名卷时,指定权限的最简单方法是什么?我不想修改我的 Dockerfile 来使用一些魔法(例如 entrypoint 执行 chown 然后执行命令)。使用 mount 选项似乎是可能的,我觉得我离解决方案很近,但也许我走错了路。


我认为这个链接可能对你有帮助,你可以试一下吗? - Noam Yizraeli
2个回答

2

我不完全确定您的问题是什么,但这对我有用:

docker run --name test_named_volume \
  --mount type=volume,source=test_vol,target=/home/user \
  --user user \
  test_named_volume touch /home/user/a

我认为你可能出错的地方是:
  1. 你的挂载目标 /home/user/test 还没有被创建,因为 Dockerfile 中的 useradd 命令只创建了 $HOME (/home/user)。所以 docker 用 root 权限在容器中创建了该目录。

  2. 你没有使用 --user 标志在 docker run 中运行指定用户的容器。


不幸的是,我真的需要将卷挂载到容器中尚不存在的文件夹(/home/user/test)上。我的用例比提供的示例要复杂一些。实际上,test文件夹是一个配置文件夹(.config),入口点是由user运行的可执行文件(su user -c <executable>),将数据存储在那个.config文件夹中。但基本上这就是我解释的同样的问题,希望这能为我的问题提供更多背景信息。 - norbjd
在这种情况下,您可以通过两种方式解决 - 在Dockerfile中预先创建文件夹,或者更改父目录的权限(您知道该目录将存在于/home/user/中)并挂载此目录。 - moebius
正如我在上一段所说,修改Dockerfile并不是一个适合的解决办法。将/home/user目录挂载到一个卷上当然可行,但如果我有多个文件夹在该目录下,并且想要将不同的目录( /home/user/test1, /home/user/test2, ...) 分别挂载到不同的卷上,那么这些解决方案就不再适用了。这就是为什么我尝试使用mount选项的原因。 - norbjd
我遇到了同样的问题,但找不到解决方案。在Docker配置中将权限设置为新创建的挂载点就像数学中的“1+1=2”一样简单。有很多人都遇到了这个问题,但我不知道为什么自从版本1以来就没有得到支持。 - Kamen Stoykov

1

刚刚遇到了这个问题。与普遍的看法相反,挂载点并没有继承主机挂载目录的权限,而是重置了它们。

当我这样做时,容器内的权限被更改为777...


volumes:
    - ./astro-nginx-php7/logs:/home/webowner/zos/log:rw

:rw 对我来说非常重要。我的镜像是 nginx:latest。 Docker Compose 版本 3.3


我无法重现这个问题。也许你正在运行docker-for-mac,它可能具有不同的卷权限行为。 - maxm
这对我也起作用了,同样在Docker for Mac上。 - VirtualWolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接