考虑以下简单的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
首先解决了这个问题,但代价是链接卷更改权限(如果我们链接卷,显然只会出现问题)。
答案 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
-e HOST_UID =`id -u`
-v $ {HOST_FOLDER_OWNED_BY_ROOT}:/ tmp
/tmp
中的容器内)中递归运行chown
:-c'chown -R $ {HOST_UID}:$ {HOST_UID} / tmp /'
因此,我可以将文件归还给当前用户,而不必将权限“升级”为root或sudo。
它很脏,但是可以用。希望我能帮上忙。