我在Docker中使用一个简单的Linux机器.在Linux上使用它,我克隆我的dev存储库并将repo作为卷安装在Docker中.然后,当我进入Docker容器时,卷中的文件属于组1000中的用户1000(一切都很好,因为Docker正确保留了所有文件所有者).现在我想在macOS中做同样的事情,但是在我的macOS机器上,我的uid是501而我的gid是20.但是当我去容器时,我意识到里面的文件有gid和uid 0,同样的作为根.如何在Docker中保留文件所有权?
osxfs驱动程序假装文件归容器运行的USER所有.如果您看到挂载的文件由root拥有,则您的容器可能设置为以root身份运行.
版本较长
macOS上的osxfs驱动程序对所有权有点谎言.以下是documentation(重点矿井)的相关部分:
Ownership
Initially,any containerized process that requests ownership Metadata of an object is told that its
uid
andgid
own the object. When any containerized process changes the ownership of a shared file system object,e.g. withchown
,the new ownership information is persisted in thecom.docker.owner
extended attribute of the object. Subsequent requests for ownership Metadata will return the prevIoUsly set values. Ownership-based permissions are only enforced at the OS X file system level with all accessing processes behaving as the user running Docker. If the user does not have permission to read extended attributes on an object (such as when that object’s permissions are0000
),osxfs
will attempt to add an access control list (ACL) entry that allows the user to read and write extended attributes. If this attempt fails,the object will appear to be owned by the process accessing it until the extended attribute is readable again.
换一种说法,
>在容器内部,osxfs驱动程序假装在容器中运行的任何uid / gid也是拥有已安装文件的uid / gid.
>如果你将文件(在容器中)chown到其他东西,则不对真实文件执行chown;此所有者信息存储在扩展文件属性中,该值由容器使用(并由macOS忽略).
>真实文件由拥有macOS的人在集装箱外拥有.使用那些真实的文件所有权以及运行Docker应用程序的用户的uid / gid(可能是Mac上的登录用户)来确定访问控制.
我将在Mac上使用容器作为示例.我构建了这个容器,这是它的Dockerfile的一部分:
FROM ubuntu:16.04
RUN useradd -d /planner -m planner
WORKDIR /planner
USER planner
如您所见,此容器作为用户“planner”运行.在Ubuntu中是典型的,作为第一个添加到这个新系统的用户,它的uid为1000,gid为1000.
在外面,在我的Mac上,我的uid和gid也很典型(501,20),但与我的容器中的“planner”用户不同.
我运行这个容器,安装了一个外部目录,其中包含我的代码.这样我就可以在开发期间重新加载应用程序而无需重建容器(一个常见的用例).
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
但是查看容器内的挂载目录,您可以看到虽然路径,日期和大小相同,但是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进程,您可以在此屏幕截图中看到.)
在Linux服务器上,它的工作方式与预期的一样.
例如,作为我在我的示例中使用的相同服务的一部分,我有一个postgres容器,它使用外部目录作为其数据存储.在我的Mac上,该目录中充满了我拥有的文件(但容器认为它们归用户“postgres”所有).但是,在服务器上,真实的uid保留在外部文件系统上.
$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时不应该有同样的问题.