Docker Desktop for Linux 常见问题

为什么 Docker Desktop for Linux 会运行虚拟机?

Docker Desktop for Linux 运行虚拟机 (VM) 的原因如下:

  1. 确保 Docker Desktop 在各个平台上提供一致的体验。

    在研究过程中,用户最常提及的想要 Docker Desktop for Linux 的原因是确保与所有主要操作系统具有功能一致性的,一致的 Docker Desktop 体验。使用虚拟机确保 Linux 用户的 Docker Desktop 体验将与 Windows 和 macOS 非常接近。

  2. 利用新的内核功能。

    有时我们希望使用新的操作系统功能。因为我们控制虚拟机内的内核和操作系统,所以我们可以立即将这些功能推广给所有用户,即使是那些有意坚持使用其机器操作系统 LTS 版本的用户。

  3. 增强安全性。

    容器镜像漏洞对主机环境构成安全风险。有大量的非官方镜像无法保证已针对已知漏洞进行验证。恶意用户可以将镜像推送到公共注册表,并使用不同的方法诱骗用户拉取并运行这些镜像。虚拟机方法可以降低这种威胁,因为任何获得 root 权限的恶意软件都仅限于虚拟机环境,无法访问主机。

    为什么不运行无根 Docker?尽管这具有表面上限制对 root 用户的访问权限的好处,因此在“top”中一切看起来更安全,但它允许非特权用户在其自己的用户命名空间中获得CAP_SYS_ADMIN并访问未预期由非特权用户使用的内核 API,从而导致漏洞

  4. 为了提供功能一致性和增强的安全性,同时最大限度地减少对性能的影响。

    Docker Desktop for Linux 使用的虚拟机使用VirtioFS,这是一种共享文件系统,允许虚拟机访问位于主机上的目录树。我们的内部基准测试表明,通过正确的虚拟机资源分配,可以使用 VirtioFS 实现接近本机的文件系统性能。

    因此,我们调整了 Linux 版 Docker Desktop 中虚拟机可用的默认内存。您可以使用 Docker Desktop 的**设置** > **资源**选项卡中的**内存**滑块根据您的具体需求调整此设置。

如何启用文件共享?

Linux 版 Docker Desktop 使用 VirtioFS作为主机和 Docker Desktop 虚拟机之间启用文件共享的默认(也是目前唯一)机制。

为了不需要提升权限,又不会不必要地限制对共享文件的操作,Docker Desktop 在用户命名空间 (参见user_namespaces(7)) 内运行文件共享服务 (virtiofsd),并配置了 UID 和 GID 映射。因此,Docker Desktop 依赖于主机已配置为启用当前用户使用从属 ID 委派。为此,必须存在/etc/subuid (参见subuid(5)) 和/etc/subgid (参见subgid(5))。Docker Desktop 只支持通过文件配置的从属 ID 委派。Docker Desktop 将当前用户 ID 和 GID 映射到容器中的 0。它使用/etc/subuid/etc/subgid中对应于当前用户的第一个条目来设置容器中 0 以上 ID 的映射。

容器中的 ID主机上的 ID
0 (root)运行 DD 的用户 ID(例如 1000)
10 +/etc/subuid//etc/subgid中指定的 ID 范围的起始值(例如 100000)
21 +/etc/subuid//etc/subgid中指定的 ID 范围的起始值(例如 100001)
32 +/etc/subuid//etc/subgid中指定的 ID 范围的起始值(例如 100002)
......

如果缺少/etc/subuid/etc/subgid,则需要创建它们。两者都应包含以下形式的条目:<用户名>:<ID 范围的起始值>:<ID 范围大小>。例如,要允许当前用户使用 100000 到 165535 的 ID

$ grep "$USER" /etc/subuid >> /dev/null 2&>1 || (echo "$USER:100000:65536" | sudo tee -a /etc/subuid)
$ grep "$USER" /etc/subgid >> /dev/null 2&>1 || (echo "$USER:100000:65536" | sudo tee -a /etc/subgid)

要验证配置是否已正确创建,请检查其内容。

$ echo $USER
exampleuser
$ cat /etc/subuid
exampleuser:100000:65536
$ cat /etc/subgid
exampleuser:100000:65536

在这种情况下,如果在 Docker Desktop 容器内更改了共享文件的属主 (chown),而该文件的属主是 UID 为 1000 的用户,则它在主机上显示为属主是 UID 为 100999 的用户。这具有不幸的副作用,即阻止了对主机上此类文件的轻松访问。可以通过创建一个具有新 GID 的组并将我们的用户添加到该组,或者通过为与 Docker Desktop 虚拟机共享的文件夹设置递归 ACL (参见setfacl(1)) 来解决此问题。

Docker Desktop 在哪里存储 Linux 容器?

Docker Desktop 将 Linux 容器和镜像存储在 Linux 文件系统中的单个大型“磁盘镜像”文件中。这与 Linux 上的 Docker 不同,后者通常将容器和镜像存储在主机的文件系统上的/var/lib/docker目录中。

磁盘镜像文件在哪里?

要找到磁盘镜像文件,请从 Docker Desktop 仪表板中选择**设置**,然后从**资源**选项卡中选择**高级**。

**高级**选项卡显示磁盘镜像的位置。它还显示磁盘镜像的最大大小和磁盘镜像实际占用的空间。请注意,其他工具可能会根据最大文件大小而不是实际文件大小显示文件的使用空间。

如果文件太大怎么办?

如果磁盘镜像文件太大,您可以

  • 将其移动到更大的驱动器
  • 删除不必要的容器和镜像
  • 减小文件的最大允许大小
如何将文件移动到更大的驱动器?

要将磁盘镜像文件移动到其他位置

  1. 选择**设置**,然后从**资源**选项卡中选择**高级**。

  2. 在**磁盘镜像位置**部分,选择**浏览**并为磁盘镜像选择新位置。

  3. 选择**应用并重启**以使更改生效。

不要直接在 Finder 中移动文件,因为这可能会导致 Docker Desktop 丢失文件的跟踪。

如何删除不必要的容器和镜像?

检查您是否有任何不必要的容器和镜像。如果您的客户端和守护进程 API 运行的是 1.25 或更高版本 (使用客户端上的docker version命令检查您的客户端和守护进程 API 版本),则可以通过运行以下命令查看详细的空间使用信息:

$ docker system df -v

或者,要列出镜像,请运行:

$ docker image ls

要列出容器,请运行:

$ docker container ls -a

如果有很多冗余对象,请运行以下命令:

$ docker system prune

此命令将删除所有停止的容器、未使用的网络、悬空镜像和构建缓存。

根据磁盘镜像文件的格式,回收主机上的空间可能需要几分钟时间。

  • 如果文件名为Docker.raw:主机上的空间应在几秒钟内回收。
  • 如果文件名为Docker.qcow2:后台进程几分钟后将释放空间。

只有在删除镜像时才会释放空间。删除运行容器内的文件时不会自动释放空间。要随时触发空间回收,请运行以下命令:

$ docker run --privileged --pid=host docker/desktop-reclaim-space

请注意,许多工具报告的是最大文件大小,而不是实际文件大小。要从终端查询主机上文件的实际大小,请运行:

$ cd ~/.docker/desktop/vms/0/data
$ ls -klsh Docker.raw
2333548 -rw-r--r--@ 1 username  staff    64G Dec 13 17:42 Docker.raw

在此示例中,磁盘的实际大小为2333548 KB,而磁盘的最大大小为64 GB。

如何减小文件的大小?

要减小磁盘镜像文件的大小

  1. 从 Docker Desktop 仪表板中选择**设置**,然后从**资源**选项卡中选择**高级**。

  2. **磁盘镜像大小**部分包含一个滑块,允许您更改磁盘镜像的最大大小。调整滑块以设置较低的限制。

  3. 选择**应用并重启**。

减小最大大小时,当前磁盘镜像文件将被删除,因此所有容器和镜像都将丢失。