在Docker中以非root用户身份挂载“命名卷”

16

有没有办法以非root用户的身份挂载命名卷?我试图避免在每个Dockerfile中运行chown,但我需要将挂载点写成可被非root用户写入以便能够在镜像中编写构建生成的工件。

这是我正在尝试的:

docker run --rm -it -v /home/bob/dev/:/src/dev -v builds:/mnt/build --name build hilikus/build /bin/bash

但对于第二座山,我得到了:

[user@42f237282128 ~]$ ll /mnt
total 4
drwxr-xr-x 2 root root 4096 Sep 18 19:29 build

我的另一个挂载点(/src/dev/)归用户所有,而不是根用户,因此它提供了我所需的内容;但是,我无法使用命名卷做同样的事情。

3个回答

5

命名的卷初始化为图像中该位置的内容,因此您需要在Dockerfile内设置权限:

$ cat df.vf-uid
FROM busybox
RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data

$ docker build -t test-vf -f df.vf-uid .
Sending build context to Docker daemon 23.06 MB
Step 1 : FROM busybox
 ---> 2b8fd9751c4c
Step 2 : RUN mkdir -p /data && echo "hello world" > /data/hello && chown -R 1000 /data
 ---> Using cache
 ---> 41390b132940
Successfully built 41390b132940

$ docker run -v test-vol:/data --rm -it test-vf ls -alR /data
/data:
total 12
drwxr-xr-x    2 1000     root          4096 Sep 19 15:26 .
drwxr-xr-x   19 root     root          4096 Sep 19 15:26 ..
-rw-r--r--    1 1000     root            12 Aug 22 11:43 hello

非常奇怪,我有一个与你类似的Dockerfile,但是我多了一条指令 VOLUME /data。当我像你展示的那样运行 docker run 命令时,所有东西都回到了 root 所有权下(需要注意的是我的卷在开始时是空的,所以我只更改了卷文件夹的所有权)。 - Huygens
1
我像我们这里说的那样“抓住了公牛的角”!我忽略了Dockerfile文档中的说明,它指出:“如果任何构建步骤在声明卷后更改卷内的数据,则这些更改将被丢弃。” 我刚好就犯了这个错误!VOLUME指令是在我创建文件夹并设置权限之前,所以它被简单地丢弃了。 - Huygens
1
@Huygens 我个人有一个最佳实践,就是不要将Volumes和Dockerfile混合使用。请查看我的博客文章以获取完整的解释,但你已经提到了其中一个重大问题:https://boxboat.com/2017/01/23/volumes-and-dockerfiles-dont-mix/ - BMitch
将它们在Dockerfile中声明的附加值主要有两个:即使您忘记在docker run中提供卷,它也会保留数据(并且人们可以理解命名卷是自动创建的);包装器可以通过简单地检查镜像来自动建议用户创建卷(无需文档)。但是,如果您提供了良好的文档,则这两个点就不那么重要,可以视为可选项。所有这些都是告诉您,是的,我同意您的最佳实践,它带来了更多优势(或减少了头痛)。 - Huygens
我似乎可以为单个容器中使用的命名卷设置权限,并在Dockerfile中设置。但是,如果我在两个容器中使用命名卷呢?哪个Dockerfile或哪个镜像会负责该卷的权限? - Dario Seidl
1
无论哪个先开始,一旦卷初始化,它就不会被用于更新图像或使用不同图像的卷再次初始化。 - BMitch

0

不对。猜得不错,但是uid既不能被docker volume create接受,也不能被docker run --mount接受。 - corwin.amber
@corwin.amber,你看过文档吗?你不能直接传递 --uid=nnn,必须传递 -o=uid=nnnn,这取决于你使用的存储驱动程序。 - dragon788
当然可以。前者的 --uid 会(预料中地)出现 unknown flag 错误。后者则会出现 Error response from daemon ... invalid option: "uid" 错误。抱歉。 - corwin.amber

0
你可以运行以下docker命令并像这样更改所有权: docker run --rm -v builds:/target alpine:latest sh -c 'chown 1000:1000 /target' 该命令将创建名为"builds"的命名卷,将其挂载到一个以root身份运行的小型容器,并将其所有权更改为用户ID 1000。
现在,在容器上挂载命名卷时,它将作为非root用户挂载。

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