了解docker中的用户文件所有权:如何避免更改链接卷的权限

时间:2014-10-22 04:20:30

标签: linux docker permissions rstudio

考虑以下简单的Dockerfile:

FROM debian:testing
RUN  adduser --disabled-password --gecos '' docker
RUN  adduser --disabled-password --gecos '' bob 

在一个没有别的工作目录中。构建泊坞窗图像:

docker build -t test .

然后在容器上运行bash脚本,将工作目录链接到bob主目录中的新子目录:

docker run --rm -it -v $(pwd):/home/bob/subdir test 

谁拥有容器上subdir的内容?在容器上,运行:

cd /home/bob/subdir
ls -l
我们看到

广告:

-rw-rw-r-- 1 docker docker 120 Oct 22 03:47 Dockerfile

圣洁的烟! docker拥有内容!回到容器外的主机上,我们看到我们的原始用户仍然拥有Dockerfile。让我们尝试修复bob主目录的所有权。在容器上,运行:

chown -R bob:bob /home/bob
ls -l 

我们看到了:

-rw-rw-r-- 1 bob bob 120 Oct 22 03:47 Dockerfile

但是等等!在容器外部,我们现在运行ls -l

-rw-rw-r-- 1 1001 1001 120 Oct 21 20:47 Dockerfile

我们不再拥有自己的文件。可怕的消息!


如果我们在上面的示例中只添加了一个用户,那么一切都会变得更顺利。出于某种原因,Docker似乎正在使其遇到的第一个非root用户所拥有的任何主目录(即使该用户在较早的图像上声明)。同样,此第一个用户是与我的家庭用户相同的所有权权限的用户。

问题1 这是正确的吗?有人能指出我的文档,我只是根据上面的实验推测。

问题2 :也许这只是因为它们在内核上都具有相同的数值,如果我在我的家庭用户不是id 1000的系统上进行测试,那么权限在每种情况下都会改变吗?

问题3 :当然,真正的问题是“我该怎么办?”如果bob在给定主机上以bob身份登录,则他应该能够将容器作为bob运行,并且不会在其主机帐户下更改文件权限。实际上,他实际上需要以用户docker运行容器,以避免更改他的帐户。

我听说你问为什么我还有这样一个奇怪的Dockerfile?。我有时也想知道。我正在为webapp(RStudio-server)编写一个容器,允许不同的用户登录,这只是使用linux机器上的用户名和凭据作为有效的用户名。这给我带来了想要创建多个用户的不同寻常的动机。我可以通过仅在运行时创建用户来解决这个问题,并且一切都很好。但是,我使用添加了单个docker用户的基本映像,以便可以交互使用它而无需以root身份运行(根据最佳实践)。这会破坏所有内容,因为该用户成为第一个用户并最终拥有所有内容,因此尝试以其他用户身份登录失败(应用无法启动,因为它缺少写入权限)。启动脚本运行chown首先解决了这个问题,但代价是链接卷更改权限(如果我们链接卷,显然只会出现问题)。

3 个答案:

答案 0 :(得分:51)

我找到了两个选项:

清除所有事情(完成工作后)

我已完成docker run -v `pwd`/shared:/shared image,并且容器已在pwd/shared内创建了文件,这些文件是docker进程拥有的。但是,/shared仍归我所有。所以在docker过程中,我做了

chown -R `stat -c "%u:%g" /shared` /shared

在我的情况下,

stat -c "%u:%g" /shared会返回1000:1000,成为我用户的uid:gid。即使docker conatainer中没有用户1000,ID仍然存在(如果您要求用户名,stat /shared只是说“未知”。)

无论如何,chown乖乖地将/shared的内容的所有权转移到1000:1000(就其而言,它不存在,但在容器外,它就是我)。所以我现在拥有所有文件。容器仍然可以根据需要修改,因为从它的角度来看,它是root

世界上的一切都很好。

docker run -u因此创建的所有文件将自动拥有正确的所有者

另一种方法是在docker run上运行-u标志。

docker run -v `pwd`/shared:/shared -u `stat -c "%u:%g" /shared` ubuntu bash

这样,容器内的docker用户为youruid:yourgid

但是:这意味着放弃容器内的root权限(apt-get install等)。除非您使用该新uid创建用户并将其添加到root组。

答案 1 :(得分:25)

  

这是对的吗?有人可以指出我这方面的记录,我只是根据上述实验推测。

     

也许这只是因为它们在内核上都具有相同的数值,如果我在我的家庭用户不是id 1000的系统上进行测试,那么在每种情况下都会更改权限吗?

阅读info coreutils 'chown invocation',这可能会让您更好地了解文件权限/所有权的工作原理。

但是,基本上,您机器上的每个文件都有一组固定的位,用于定义其权限和所有权。当您chown文件时,您只需设置这些位。

当您使用用户名或群组名称chown文件发送给特定用户/群组时,chown会在/etc/passwd中查找用户名,/etc/group为群组尝试将名称映射到ID。如果这些文件中不存在用户名/组名称,则chown将失败。

root@dc3070f25a13:/test# touch test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 root root    0 Oct 22 18:15 test
root@dc3070f25a13:/test# chown test:test test
chown: invalid user: 'test:test'

但是,您可以chown使用ID的文件到您想要的任何内容(当然,在某些上部正整数范围内),无论您的计算机上是否存在具有这些ID的用户/组。

root@dc3070f25a13:/test# chown 5000:5000 test
root@dc3070f25a13:/test# ll
total 8
drwxr-xr-x  2 root root 4096 Oct 22 18:15 ./
drwxr-xr-x 22 root root 4096 Oct 22 18:15 ../
-rw-r--r--  1 5000 5000    0 Oct 22 18:15 test

UID和GID位在文件本身上设置,因此当您在docker容器中挂载这些文件时,该文件具有与在主机上相同的所有者/组UID,但现在映射到{{1在容器中,除非它由root(UID 0)拥有,否则它可能会成为另一个用户。

  

当然,真正的问题是,我该怎么做?'如果bob在给定主机上以bob身份登录,则他应该能够将容器作为bob运行,并且不能在其主机帐户下更改文件权限。实际上,他实际上需要以用户泊坞窗的形式运行容器,以避免他的帐户被更改。

看来,根据您当前的设置,您需要确保您的UID>主机上/etc/passwd的用户名与您的UID匹配>容器/etc/passwd中的用户名,如果您想要与已登录的用户目录进行交互,则该用户名是在主机上登录的用户。

您可以使用/etc/passwd创建具有特定用户ID的用户。 Buuuut,这似乎是一个混乱的解决方案......

您可能需要提供一个不会挂载主机用户主目录的解决方案。

答案 2 :(得分:1)

因此,我最终在这篇文章中探讨了如何向非特权用户恢复以root用户身份运行的docker容器中所有文件(由root拥有)的所有权在主机中。

我需要容器内的进程以root身份运行,所以我不能在docker run上使用-u。

我不为自己的所作所为感到骄傲,但是在bash脚本的结尾,我添加了以下内容:

docker run --rm -it \
    --entrypoint /bin/sh \
    -e HOST_UID=`id -u` \
    -v ${HOST_FOLDER_OWNED_BY_ROOT}:/tmp \
    alpine:latest \
    -c 'chown -R ${HOST_UID}:${HOST_UID} /tmp/'

让我们细分一些行:

  • 在容器中运行/ bin / sh:
  

-入口点/ bin / sh

  • 将当前用户的uid作为环境变量传递给容器:
  

-e HOST_UID =`id -u`

  • 在该新容器的{{下,安装要重新归还给用户的任何文件夹(由root拥有的文件填充,由先前以root用户身份运行的容器输出) 1}}:
  

-v $ {HOST_FOLDER_OWNED_BY_ROOT}:/ tmp

  • 使用主机用户的uid在目标目录(安装在/tmp中的容器内)中递归运行chown
  

-c'chown -R $ {HOST_UID}:$ {HOST_UID} / tmp /'

因此,我可以将文件归还给当前用户,而不必将权限“升级”为root或sudo。

它很脏,但是可以用。希望我能帮上忙。