了解 Mac 上 Docker Desktop 的权限要求

此页面包含有关在 Mac 上运行和安装 Docker Desktop 的权限要求的信息。

它还提供了运行容器的清晰性,而root不是root在主机上的访问权限。

权限要求

Mac 版 Docker Desktop 以非特权用户身份运行。但是,Docker Desktop 需要某些功能来执行一组有限的特权配置,例如:

  • 在 中安装符号链接/usr/local/bin
  • 绑定小于 1024 的特权端口。所谓的“特权端口”通常不用作安全边界,但操作系统仍然阻止非特权进程绑定它们,从而破坏docker run -p 127.0.0.1:80:80 docker/getting-started.
  • 确保localhostkubernetes.docker.internal定义/etc/hosts。一些旧的 macOS 安装没有localhostin /etc/hosts,这会导致 Docker 失败。定义 DNS 名称kubernetes.docker.internal允许 Docker 与容器共享 Kubernetes 上下文。
  • 安全缓存注册表访问管理策略,该策略对开发人​​员来说是只读的。

根据使用的 Docker Desktop for Mac 版本,在安装期间、首次运行期间或仅在需要时授予特权访问权限。


从版本 4.18 及更高版本开始,Docker Desktop for Mac 可以更好地控制安装过程中启用的功能。

Docker Desktop for Mac 首次启动时,会显示一个安装窗口,您可以在其中选择使用默认设置(这适用于大多数开发人员,需要您授予特权访问权限)或使用高级设置。

如果您在安全要求较高的环境中工作,例如禁止本地管理访问,则可以使用高级设置来消除授予特权访问的需要。您可以配置:

  • Docker CLI 工具在系统或用户目录中的位置
  • 默认的 Docker 套接字
  • 特权端口映射

根据您配置的高级设置,您必须输入密码进行确认。

您可以稍后从“设置”中的“高级”页面更改这些配置。

Docker Desktop for Mac 版本 4.15 至 4.17 不需要特权进程即可永久运行。每当配置需要提升权限时,Docker Desktop 都会提示您有关其需要执行的任务的信息。大多数配置仅应用一次,后续运行不再提示特权访问。 Docker Desktop 唯一可能启动特权进程的时间是绑定主机操作系统默认情况下不允许的特权端口。

Docker Desktop for Mac 4.15 之前的版本需要root在首次运行时授予访问权限。 Docker Desktop 首次启动时,您会收到管理员提示,要求授予安装com.docker.vmnetd特权帮助程序服务的权限。对于后续运行,root不需要特权。遵循最小权限原则,这种方法允许root仅将访问权限用于绝对必要的操作,同时仍然能够以非特权用户身份使用 Docker Desktop。所有特权操作都使用特权帮助进程来运行com.docker.vmnetd


Docker 二进制文件默认安装在/Applications/Docker.app/Contents/Resources/bin. Docker Desktop 为 中的二进制文件创建符号链接/usr/local/bin,这意味着它们会自动包含在PATH大多数系统中。


在 4.18 及更高版本中,您可以选择是否在Docker Desktop 安装中/usr/local/bin或安装过程中安装符号链接。$HOME/.docker/bin

如果/usr/local/bin选择 ,并且非特权用户无法写入此位置,则 Docker Desktop 需要授权才能确认此选择,然后才能在/usr/local/bin.如果$HOME/.docker/bin选择,则不需要授权,但您必须 手动添加$HOME/.docker/bin到其 PATH。

您还可以选择启用/var/run/docker.sock符号链接的安装。创建此符号链接可确保依赖默认 Docker 套接字路径的各种 Docker 客户端无需进行额外更改即可工作。

由于/var/run作为 tmpfs 挂载,其内容在重新启动时将被删除,其中包括指向 Docker 套接字的符号链接。为了确保 Docker 套接字在重新启动后存在,Docker Desktop 设置了一个launchd启动任务,通过运行 来创建符号链接ln -s -f /Users/<user>/.docker/run/docker.sock /var/run/docker.sock。这可确保每次启动时不会提示您创建符号链接。如果您在安装时未启用此选项,则不会创建符号链接和启动任务,并且您可能必须在其使用的客户端中显式设置DOCKER_HOST环境变量。 /Users/<user>/.docker/run/docker.sockDocker CLI 依赖当前上下文来检索套接字路径,当前上下文设置desktop-linux为 Docker Desktop 启动时。

对于 4.18 之前的版本,安装符号链接/usr/local/bin是 Docker Desktop 在首次启动时执行的特权配置。 Docker Desktop 检查符号链接是否存在并执行以下操作:

  • /usr/local/bin如果非特权用户可写,则在没有管理提示的情况下创建符号链接。
  • 触发管理员提示,要求您授权在/usr/local/bin.如果您授权这样做,则会在/usr/local/bin.如果您拒绝提示,不愿意运行需要提升权限的配置,或者在您的计算机上没有管理员权限,Docker Desktop 会创建符号链接~/.docker/bin并编辑您的 shell 配置文件,以确保此位置位于您的 PATH 中。这需要重新加载所有打开的炮弹。系统会记录拒绝情况以供将来运行,以避免再次提示您。如果无法确保二进制文件位于您的 PATH 上,您可能需要手动添加到其 PATH 中/Applications/Docker.app/Contents/Resources/bin或使用 Docker 二进制文件的完整路径。

一个特殊的情况是符号链接的安装/var/run/docker.sock。创建此符号链接可确保依赖默认 Docker 套接字路径的各种 Docker 客户端无需进行额外更改即可工作。由于/var/run作为 tmpfs 挂载,其内容在重新启动时将被删除,包括到 Docker 套接字的符号链接。为了确保 Docker 套接字在重新启动后存在,Docker Desktop 设置了一个launchd启动任务,通过运行 来创建符号链接ln -s -f /Users/<user>/.docker/run/docker.sock /var/run/docker.sock。这可确保每次启动时不会提示您创建符号链接。如果您拒绝提示,则不会创建符号链接和启动任务,并且您可能必须在其使用的客户端中显式DOCKER_HOST设置。 /Users/<user>/.docker/run/docker.sockDocker CLI 依赖当前上下文来检索套接字路径,当前上下文设置desktop-linux为 Docker Desktop 启动时。


绑定特权端口


对于 4.18 及更高版本,您可以选择在安装过程中启用特权端口映射,或者在安装后的“设置”中的“高级”页面中启用。 Docker Desktop 需要授权才能确认此选择。

对于 4.18 以下的版本,如果运行需要绑定特权端口的容器,Docker Desktop 首先尝试将其直接绑定为非特权进程。如果操作系统阻止此操作并且失败,Docker Desktop 会检查com.docker.vmnetd特权帮助程序进程是否正在运行,以通过它绑定特权端口。

如果特权帮助程序进程未运行,Docker Desktop 会提示您授权在 launchd下运行它。这会将特权帮助程序配置为在 4.15 之前的 Docker Desktop 版本中运行。但是,此特权帮助程序提供的功能现在仅支持端口绑定和缓存注册表访问管理策略。如果您拒绝启动特权帮助程序进程,则无法绑定特权端口,并且 Docker CLI 返回错误:

$ docker run -p 127.0.0.1:80:80 docker/getting-started

docker: Error response from daemon: Ports are not available: exposing port
TCP 127.0.0.1:80 -> 0.0.0.0:0: failed to connect to /var/run/com.docker.vmnetd.sock:
is vmnetd running?: dial unix /var/run/com.docker.vmnetd.sock: connect: connection
refused.
ERRO[0003] error waiting for container: context canceled

笔记

如果您花费太长时间来授权启动帮助程序进程的提示,则该命令可能会失败并出现相同的错误,因为它可能会超时。


确保定义了 localhost 和 kubernetes.docker.internal


对于 4.18 及更高版本,您有责任确保 localhost 解析为127.0.0.1,如果使用 Kubernetes,则kubernetes.docker.internal解析为127.0.0.1.

首次运行时,Docker Desktop 检查是否localhost解析为127.0.0.1.如果解析失败,它会提示您允许将映射添加到/etc/hosts.同样,当安装 Kubernetes 集群时,它会检查是否kubernetes.docker.internal已解析127.0.0.1并提示您执行此操作。


从命令行安装

在 Docker Desktop for Mac 版本 4.11 及更高版本中,在安装过程中使用install 命令--user上的标志 应用特权配置。在这种情况下,首次运行 Docker Desktop 时不会提示您授予 root 权限。具体来说,该标志:--user

  • 卸载以前的版本com.docker.vmnetd(如果存在)
  • 设置符号链接
  • 确保localhost解决127.0.0.1

这种方法的限制是 Docker Desktop 只能由每台机器的一个用户帐户运行,即标志中指定的用户帐户-–user

特权帮手

在需要特权帮助程序的有限情况下,例如绑定特权端口或缓存注册表访问管理策略,特权帮助程序由launchd后台启动并在后台运行,除非如前所述在运行时禁用它。 Docker Desktop 后端通过 UNIX 域套接字与特权助手进行通信/var/run/com.docker.vmnetd.sock。它执行的功能是:

  • 绑定小于1024的特权端口。
  • 安全缓存注册表访问管理策略,该策略对开发人​​员来说是只读的。
  • 卸载特权助手。

特权帮助进程的删除与删除进程的方式相同launchd

$ ps aux | grep vmnetd
root             28739   0.0  0.0 34859128    228   ??  Ss    6:03PM   0:00.06 /Library/PrivilegedHelperTools/com.docker.vmnetd
user             32222   0.0  0.0 34122828    808 s000  R+   12:55PM   0:00.00 grep vmnetd

$ sudo launchctl unload -w /Library/LaunchDaemons/com.docker.vmnetd.plist
Password:

$ ps aux | grep vmnetd
user             32242   0.0  0.0 34122828    716 s000  R+   12:55PM   0:00.00 grep vmnetd

$ rm /Library/LaunchDaemons/com.docker.vmnetd.plist

$ rm /Library/PrivilegedHelperTools/com.docker.vmnetd

在 Linux VM 中以 root 身份运行的容器

借助 Docker Desktop,Docker 守护进程和容器在由 Docker 管理的轻量级 Linux VM 中运行。这意味着虽然容器默认运行为 root,但这不会授予root对 Mac 主机的访问权限。 Linux VM 充当安全边界并限制可以从主机访问的资源。挂载到 Docker 容器中的主机绑定的任何目录仍保留其原始权限。

增强容器隔离

此外,Docker Desktop 支持 增强型容器隔离模式(ECI),仅适用于企业客户,从而进一步保护容器,而不影响开发人员工作流程。

ECI 自动运行 Linux 用户命名空间内的所有容器,以便容器中的根映射到 Docker Desktop VM 内的非特权用户。 ECI 使用此技术和其他先进技术来进一步保护 Docker Desktop Linux VM 中的容器,以便它们进一步与 Docker 守护程序和 VM 内运行的其他服务隔离。