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

2024-10-25 08:42:00
admin
原创
97
摘要:问题描述:考虑以下简单的 Dockerfile:FROM debian:testing RUN adduser --disabled-password --gecos '' docker RUN adduser --disabled-password --gecos &...

问题描述:

考虑以下简单的 Dockerfile:

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

在一个没有其他内容的工作目录中。构建 docker 镜像:

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 这么奇怪?有时我也很想知道。我正在为一个允许不同用户登录的 web 应用程序(RStudio-server)编写容器,它只是使用来自 linux 机器的用户名和凭据作为有效用户名。这给我带来了想要创建多个用户的不寻常的动机。我可以通过只在运行时创建用户来解决这个问题,一切都很好。但是,我使用了一个添加了单个docker用户的基本映像,这样就可以在不以 root 身份运行的情况下以交互方式使用它(按照最佳实践)。这会毁了一切,因为该用户成为第一个用户并最终拥有所有内容,因此尝试以其他用户身份登录会失败(应用程序无法启动,因为它缺乏写权限)。首先运行启动脚本可以chown解决这个问题,但代价是链接卷会改变权限(显然只有在我们链接卷时才会出现问题)。


解决方案 1:

我发现了两个选项:

完成工作后,清理所有东西

我已经完成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乖乖地将 内容的所有权转让/shared1000:1000(就它而言,它并不存在,但在容器之外,它属于我)。所以我现在拥有所有文件。容器仍然可以根据需要修改内容,因为从它的角度来看,它是root

世界一切安好。

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

另一种方法是-u使用 docker run 上的标志。

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

这样容器里面的docker用户就是了youruid:yourgid

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

解决方案 2:

对吗?有人能给我指出这方面的文献吗?我只是根据上述实验进行推测。

也许这只是因为它们在内核上具有相同的数值,并且如果我在家庭用户 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,但现在映射到/etc/passwd容器中,除非它由 root(UID 0)拥有,否则它可能会是不同的用户。

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

看起来,使用您当前的设置,如果您想以登录主机的同一用户身份与已挂载的用户目录进行交互,则需要确保/etc/passwd主机上的 UID > 用户名与容器中的 UID > 用户名匹配/etc/passwd

您可以使用 创建具有特定用户 ID 的用户useradd -u xxxx。但是,这似乎是一个混乱的解决方案……

您可能必须想出一个不挂载主机用户主目录的解决方案。

解决方案 3:

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

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

我对我所做的事情并不感到自豪,但在我的 bash 脚本末尾,我添加了以下内容:

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

让我们分解一下其中的一些内容:

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

--入口点/bin/sh

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

-e HOST_UID=id -u

  • 将您想要重新拥有的任何文件夹挂载回您的用户(填充了 root 拥有的文件,由以 root 身份运行的先前容器输出),在此新容器下/tmp

-v ${HOST_FOLDER_OWNED_BY_ROOT}:/tmp

  • chown使用主机用户的 uid 对目标目录(挂载在容器内)进行递归运行/tmp

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

因此,通过这个,我将文件所有权交还给我当前用户,而无需“升级”权限到 root 或 sudo。

虽然很脏,但还是有用。希望我帮到了你。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用