MacOSX上的Docker无法正确翻译卷中的文件所有权

时间:2017-03-29 15:05:11

标签: macos docker

我在Docker中使用一个简单的Linux机器。在Linux上使用它,我克隆我的dev存储库并将repo作为卷安装在Docker中。然后,当我进入Docker容器时,卷中的文件属于组1000中的用户1000(一切都很好,因为Docker正确保留了所有文件所有者)。现在我试图在macOS中做同样的事情,但是在我的macOS机器上,我的uid是501而我的gid是20.但是当我去容器时,我意识到里面的文件有gid和uid 0,和root一样。如何在Docker中保留文件所有权?

2 个答案:

答案 0 :(得分:16)

TL; DR

osxfs驱动程序假装文件归容器运行的USER所有。如果您看到挂载的文件由root拥有,则您的容器可能设置为以root身份运行。

版本较长

macOS上的osxfs驱动程序对所有权有点谎言。以下是documentation(强调我的)的相关部分:

  

所有权

     

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

换句话说,

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

  2. 如果您将文件(在容器中)chown到其他内容,则不会对真实文件执行任何chown;此所有者信息存储在扩展文件属性中,该值由容器使用(并由macOS忽略)。

  3. 真实文件由拥有macOS的人在集装箱外拥有。访问控制是使用真实的文件所有权以及运行Docker应用程序的用户的uid / gid(可能是Mac上的登录用户)确定的。

  4. 我将在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进程,如此截图所示。)

    Activity Monitoring showing Docker processes

    在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时不应该有同样的问题。

答案 1 :(得分:-3)

  

如何在docker中保留文件所有权?

为什么你需要这样做?

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

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

这是我从Mac上做的所有事情,我从来没有在编辑卷中的文件或将这些更改反映在容器中的问题