Docker Desktop for Linux 的常见问题
为什么 Docker Desktop for Linux 运行一个 VM?
Docker Desktop for Linux 运行虚拟机 (VM) 的原因如下:
确保 Docker Desktop 在不同平台提供一致的体验。
在研究中,用户希望 Docker Desktop for Linux 的最常被提及的原因是确保所有主要操作系统上的 Docker Desktop 体验具有功能对等性。使用 VM 确保了 Linux 用户的 Docker Desktop 体验将与 Windows 和 macOS 用户的体验非常接近。
利用新的内核特性。
有时我们想利用新的操作系统特性。由于我们控制着 VM 内部的内核和操作系统,我们可以立即将其推广给所有用户,甚至包括那些故意坚持使用其机器操作系统的 LTS 版本的用户。
增强安全性。
容器镜像漏洞对宿主环境构成安全风险。存在大量未经官方验证的非官方镜像,不能保证其没有已知漏洞。恶意用户可以将镜像推送到公共注册表,并使用不同方法诱骗用户拉取并运行它们。VM 方法可以缓解此威胁,因为任何获得 root 权限的恶意软件都将限制在 VM 环境中,无法访问宿主。
为什么不运行无根 Docker?虽然这表面上限制了对 root 用户的访问,使得一切在“top”中看起来更安全,但它允许非特权用户在其自己的用户命名空间中获得
CAP_SYS_ADMIN并访问不期望由非特权用户使用的内核 API,从而导致漏洞。在对性能影响最小的情况下,提供功能对等和增强安全性的好处。
Docker Desktop for Linux 使用的 VM 使用
VirtioFS,这是一个共享文件系统,允许虚拟机访问位于主机上的目录树。我们的内部基准测试显示,通过为 VM 分配合适的资源,VirtioFS 可以实现接近原生的文件系统性能。因此,我们调整了 Docker Desktop for Linux 中 VM 的默认内存。您可以通过使用 Docker Desktop 的 Settings > Resources 选项卡中的 Memory 滑块,根据您的特定需求调整此设置。
如何启用文件共享?
Docker Desktop for Linux 使用 VirtioFS 作为在宿主和 Docker Desktop VM 之间启用文件共享的默认(目前也是唯一)机制。
为了不要求提升权限,同时不无故限制共享文件的操作,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) | 运行 Docker Desktop 的用户 ID (例如 1000) |
| 1 | 0 + /etc/subuid//etc/subgid 中指定的 ID 范围的开头 (例如 100000) |
| 2 | 1 + /etc/subuid//etc/subgid 中指定的 ID 范围的开头 (例如 100001) |
| 3 | 2 + /etc/subuid//etc/subgid 中指定的 ID 范围的开头 (例如 100002) |
| ... | ... |
如果缺少 /etc/subuid 和 /etc/subgid,则需要创建它们。两者都应包含以下形式的条目 - <username>:<id 范围的开始>:<id 范围大小>。例如,要允许当前用户使用从 100 000 到 165 535 的 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 容器中一个共享文件被用户 UID 为 1000 的用户 chown,它在主机上会显示为 UID 为 100999 的用户所有。这有一个不幸的副作用,阻止了在主机上轻松访问此类文件。通过创建一个具有新 GID 的组并将我们的用户添加到其中,或者为与 Docker Desktop VM 共享的文件夹设置递归 ACL(参见 setfacl(1)),可以解决此问题。
Docker Desktop 将 Linux 容器存储在哪里?
Docker Desktop 将 Linux 容器和镜像存储在 Linux 文件系统中的单个大“磁盘镜像”文件中。这与 Linux 上的 Docker 不同,后者通常将容器和镜像存储在主机文件系统的 /var/lib/docker 目录中。
磁盘镜像文件在哪里?
要找到磁盘镜像文件,请从 Docker Desktop Dashboard 选择 Settings,然后从 Resources 选项卡中选择 Advanced。
Advanced 选项卡显示磁盘镜像的位置。它还显示磁盘镜像的最大大小以及磁盘镜像实际占用的空间。请注意,其他工具可能会以最大文件大小而不是实际文件大小来显示文件的空间使用情况。
如果文件太大怎么办?
如果磁盘镜像文件太大,您可以
- 将其移动到更大的驱动器
- 删除不必要的容器和镜像
- 减小文件的最大允许大小
如何将文件移动到更大的驱动器?
要将磁盘镜像文件移动到其他位置
选择 Settings,然后从 Resources 选项卡中选择 Advanced。
在 Disk image location 部分,选择 Browse 并为磁盘镜像选择一个新位置。
选择 Apply 以使更改生效。
不要直接在 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。
如何减小文件的最大大小?
要减小磁盘镜像文件的最大大小
从 Docker Desktop Dashboard 选择 Settings,然后从 Resources 选项卡中选择 Advanced。
Disk image size 部分包含一个滑块,允许您更改磁盘镜像的最大大小。调整滑块以设置下限。
选择**应用**。
当您减小最大大小时,当前的磁盘镜像文件将被删除,因此所有容器和镜像都将丢失。