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

2024-10-25 08:42:00
admin
原创
411
摘要:问题描述:考虑以下简单的 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。

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用