MacOSX上的Docker不会正确转换卷的文件所有权

我在Docker中使用了一个简单的Linux机器。 在Linux中使用它,我克隆我的开发库,并在Docker中作为一个卷挂载回购。 然后,当我进入Docker容器时,卷中的文件属于组1000中的用户1000(一切正常,因为Docker保持正确的所有文件所有者)。 现在我试图在macOS中做同样的事情,但在我的macOS机器上,我的uid是501,我的gid是20.但是当我去容器时,我意识到里面的文件有gid和uid 0,作为根。 我能做些什么来保持Docker中的文件所有权?

TL; DR

osxfs驱动程序假装文件由容器运行的USER拥有。 如果您将装入的文件视为由root拥有,则您的容器可能设置为以root用户身份运行。


更长的版本

macOS上的osxfs驱动程序讲述了关于所有权的一些谎言。 这里是文档的相关部分(重点是我的):

所有权

最初,任何请求所有权对象的元数据的容器化过程都被告知它的uidgid拥有这个对象 。 当任何容器化过程改变了共享文件系统对象的所有权时,例如使用chown ,新的所有权信息被保存在对象的com.docker.owner扩展属性中。 随后的所有权元数据请求将返回以前设置的值。 基于所有权的权限仅在OS X文件系统级别执行,所有访问进程都像运行Docker的用户一样运行。 如果用户没有权限读取对象的扩展属性(例如对象的权限为0000 ),则osxfs将尝试添加允许用户读取和写入扩展属性的访问控制列表(ACL)条目。 如果这个尝试失败了,那么这个对象将会被访问它的进程拥有,直到扩展属性再次被读取为止。

换一种说法,

  1. 在容器内部,osxfs驱动程序假装在容器中运行的任何uid / gid也是拥有已装载文件的uid / gid。

  2. 如果你把文件(在容器中)换成别的东西,那么对真实文件就不会执行chown了。 这个所有者信息被存储在一个扩展的文件属性中,而这个值被容器使用(并被macOS忽略)。

  3. 真正的文件由拥有MacOS的人在容器外拥有。 访问控制是使用这些真正的文件所有权以及运行Docker应用程序的用户的uid / gid(这可能是Mac上的login用户)来确定的。

我将以Mac上的一个容器为例。 我build立了这个容器,这里是它的Dockerfile的一部分:

 FROM ubuntu:16.04 RUN useradd -d /planner -m planner WORKDIR /planner USER planner 

正如你所看到的,这个容器作为用户“计划者”运行。 正如Ubuntu中的典型情况,作为第一个添加到这个新系统的用户,它有一个1000和一个1000的gid。

外面,在我的Mac上,我的uid和gid也是典型的(501,20),但与我的容器中的“planner”用户不同。

我运行这个容器与一个外部目录挂载,其中包含我的代码。 这样,我可以在开发过程中重新加载应用程序,而无需重新构build容器(一个常见的用例)。

 version: '2' services: uwsgi: image: planner:latest build: ./uwsgi volumes: - ./uwsgi/planner:/planner 

如果我在我的Mac上查看源代码目录( ./uwsgi/planner ),这些文件归我所有(uid 501,gid 20)。

 -rw-r--r-- 1 dan staff 3103 Oct 24 23:28 README.md drwxr-xr-x 4 dan staff 136 Sep 14 2016 doc -rwxr-xr-x 1 dan staff 260 Sep 14 2016 manage.py drwxr-xr-x 7 dan staff 238 Jan 11 00:00 site_planner drwxr-xr-x 4 dan staff 136 Jan 10 19:07 node_modules drwxr-xr-x 12 dan staff 408 Mar 30 12:30 planner -rw-r--r-- 1 dan staff 112 Oct 5 10:28 requirements.txt 

但是查看容器中的挂载目录,可以看到虽然path,date和大小相同,但osxfs已经屏蔽了所有者,并告诉容器操作系统这些文件实际上由“planner”拥有。 用户的实际名称和uid在这里并不重要。 osxfs驱动程序只是使用当前用户。 如果你有一个名为“joe”的uid 1005的用户,那么你将会看到这个。

 -rw-r--r-- 1 planner planner 3103 Oct 25 03:28 README.md drwxr-xr-x 4 planner planner 136 Sep 14 2016 doc -rwxr-xr-x 1 planner planner 260 Sep 14 2016 manage.py drwxr-xr-x 7 planner planner 238 Jan 11 05:00 site_planner drwxr-xr-x 4 planner planner 136 Jan 11 00:07 node_modules drwxr-xr-x 12 planner planner 408 Mar 30 16:30 planner -rw-r--r-- 1 planner planner 112 Oct 5 14:28 requirements.txt 

现在,这只是Mac上的osxfs驱动程序。 而且它是以简单的名义完成的 – 在Mac上你可能正在做开发工作,文件许可的细微差别只是一个你必须解决的痛苦。 另外,请注意,如果不使用sudo或其他工具提升您的权限,则无法在Mac上执行此类chown。

 $ chown 1000 manage.py chown: manage.py: Operation not permitted 

这很重要,因为除了vmnetd之外,在Mac上运行的所有Docker进程都以您的身份运行,而不是以root身份运行。 (包括osxfs进程,你可以在这个截图中看到。)

活动监视显示Docker进程

在Linux服务器上,它的工作原理与您预期的一样。 例如,作为我在示例中使用的同一个服务的一部分,我有一个postgres容器,它使用一个外部目录作为它的数据存储。 在我的Mac上,该目录充满了我拥有的文件(但容器认为它们归用户“postgres”所有)。 但是,在服务器上,真正的用户名保留在外部文件系统上。

 $ ls -ln pgdata total 120 drwx------. 6 999 999 4096 Oct 31 21:06 base drwx------. 2 999 999 4096 Mar 8 19:22 global drwx------. 2 999 999 4096 Oct 31 21:06 pg_clog drwx------. 2 999 999 4096 Oct 31 21:06 pg_commit_ts drwx------. 2 999 999 4096 Oct 31 21:06 pg_dynshmem drwx------. 4 999 999 4096 Oct 31 21:06 pg_logical drwx------. 4 999 999 4096 Oct 31 21:06 pg_multixact drwx------. 2 999 999 4096 Mar 8 19:22 pg_notify drwx------. 2 999 999 4096 Oct 31 21:06 pg_replslot drwx------. 2 999 999 4096 Oct 31 21:06 pg_serial drwx------. 2 999 999 4096 Oct 31 21:06 pg_snapshots drwx------. 2 999 999 4096 Mar 8 19:22 pg_stat drwx------. 2 999 999 4096 Apr 4 17:08 pg_stat_tmp drwx------. 2 999 999 4096 Mar 20 15:36 pg_subtrans drwx------. 2 999 999 4096 Oct 31 21:06 pg_tblspc drwx------. 2 999 999 4096 Oct 31 21:06 pg_twophase drwx------. 3 999 999 4096 Mar 17 18:30 pg_xlog -rw-------. 1 999 999 4 Oct 31 21:06 PG_VERSION -rw-------. 1 999 999 4496 Oct 31 21:06 pg_hba.conf -rw-------. 1 999 999 1636 Oct 31 21:06 pg_ident.conf -rw-------. 1 999 999 88 Oct 31 21:06 postgresql.auto.conf -rw-------. 1 999 999 22233 Oct 31 21:06 postgresql.conf -rw-------. 1 999 999 37 Mar 8 19:22 postmaster.opts -rw-------. 1 999 999 68 Mar 8 19:22 postmaster.pid 

这里的文件由uid 999,gid 999拥有。这不是我的uid(在这个特定的服务器上是5046)。

999是容器内部的 postgres的uid,这里的文件权限在外部暴露。

换句话说,你遇到的问题是Mac特有的,而且你不应该在生产中使用Linux。

我能做些什么来保持泊坞窗的文件所有权?

你为什么需要这样做?

如果你在你的容器中使用主机装入的卷(通过docker run ,例如-v $PWD:/my/app args),那么在映像本身中权限是什么并不重要。

您可以编辑您的Mac上的文件,更改将立即反映在容器中。

这是我从我的Mac所做的,我从来没有问题编辑我的卷中的文件或有这些变化反映在容器中