macos - MacOSX 上的 Docker 无法在卷中正确转换文件所有权

标签 macos docker

我在 Docker 中使用了一个简单的 Linux 机器。在 Linux 中使用它,我克隆了我的开发存储库并将该存储库作为卷安装在 Docker 中。然后,当我进入 Docker 容器时,卷中的文件属于组 1000 中的用户 1000(一切都很好,因为 Docker 正确保存了所有文件所有者)。现在我正在尝试在 macOS 中做同样的事情,但是在我的 macOS 机器中,我的 uid 是 501,我的 gid 是 20。但是当我进入容器时,我意识到它里面的文件有 gid 和 uid 0,相同作为根。我可以做些什么来保持 Docker 中的文件所有权?

最佳答案

TL;DR

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


加长版

macOS 上的 osxfs 驱动程序在所有权方面撒了一点谎。这是documentation的相关部分(强调我的):

Ownership

Initially, any containerized process that requests ownership metadata of an object is told that its uid and gid own the object. When any containerized process changes the ownership of a shared file system object, e.g. with chown, the new ownership information is persisted in the com.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 are 0000), 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.

换句话说,

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

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

  3. 真正的文件由在 macOS 中拥有它们的人拥有,在容器之外。访问控制是使用那些真实文件所有权以及运行 Docker 应用程序的用户(可能是您在 Mac 上的登录用户)的 uid/gid 确定的。

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

FROM ubuntu:16.04
RUN useradd -d /planner -m planner
WORKDIR /planner
USER 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 已经掩盖了所有者,并告诉容器操作系统这些文件实际上是由“计划者”拥有的。用户的实际名称和 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 应该不会遇到同样的问题。

关于macos - MacOSX 上的 Docker 无法在卷中正确转换文件所有权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43097341/

相关文章:

objective-c - 如何阻止 NSSavePanel 在完成 block 后关闭?

java - 为 IntelliJ 13 设置 Maven

macos - 如何创建符号链接(symbolic link)以在 Mac osx 的终端中打开目录?

java - Intellij IDEA无法构建简单类

从 docker 容器到主机超时的 curl 请求

docker - nvidia-docker run 与 docker run --runtime=nvidia

ubuntu - 入口点脚本 : "no such file or directory" 上的 Docker 错误

linux - PID 启动过程污染

linux - Linux Mint 端口上的 Docker 配置与 dnsmasq 冲突

proxy - 代理后面的 Docker-Machine 和 Swarm