Docker Desktop for Linux 常见问题
为什么 Docker Desktop for Linux 运行虚拟机?
Docker Desktop for Linux 运行虚拟机 (VM) 的原因如下
确保 Docker Desktop 在不同平台提供一致的体验。
在研究过程中,用户希望使用 Docker Desktop for Linux 最常提及的原因是确保在所有主要操作系统上都能获得功能一致的 Docker Desktop 体验。使用虚拟机可以确保 Linux 用户的 Docker Desktop 体验与 Windows 和 macOS 非常相似。
利用新的内核功能。
有时我们希望利用新的操作系统功能。由于我们控制虚拟机内部的内核和操作系统,因此我们可以立即向所有用户推出这些功能,即使是那些有意停留在其机器操作系统的 LTS 版本的用户。
增强安全性。
容器镜像漏洞对主机环境构成安全风险。存在大量非官方镜像,无法保证已针对已知漏洞进行验证。恶意用户可以将镜像推送到公共注册表,并使用不同的方法诱骗用户拉取和运行它们。虚拟机方法缓解了这一威胁,因为任何获取 root 权限的恶意软件都仅限于虚拟机环境,无法访问主机。
为什么不运行无根 Docker?虽然这在表面上限制了对 root 用户的访问,使得在 "top" 中看起来更安全,但这允许非特权用户在其自身的用户命名空间中获得
CAP_SYS_ADMIN
权限,并访问内核 API(这些 API 不期望被非特权用户使用),从而导致漏洞。在提供功能一致性和增强安全性的同时,对性能影响最小。
Docker Desktop for Linux 使用的虚拟机使用了
VirtioFS
,这是一个共享文件系统,允许虚拟机访问位于主机上的目录树。我们的内部基准测试表明,通过为虚拟机分配适当的资源,VirtioFS 可以实现接近原生文件系统的性能。因此,我们调整了 Docker Desktop for Linux 中可供虚拟机使用的默认内存。您可以通过 Docker Desktop 的 Settings > Resources 选项卡中的 Memory 滑块根据您的特定需求调整此设置。
如何启用文件共享?
Docker Desktop for Linux 使用 VirtioFS 作为主机与 Docker Desktop 虚拟机之间文件共享的默认(也是目前唯一)机制。
为了不要求提升权限,同时不必要地限制对共享文件的操作,Docker Desktop 在配置了 UID 和 GID 映射的用户命名空间(参见 user_namespaces(7)
)中运行文件共享服务 (virtiofsd
)。因此,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>:<start of id range>:<id range size>
。例如,允许当前用户使用从 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 虚拟机共享的文件夹设置递归 ACL(参见 setfacl(1)
)。
Docker Desktop 将 Linux 容器存储在哪里?
Docker Desktop 将 Linux 容器和镜像存储在 Linux 文件系统中的一个大型“磁盘镜像”文件中。这与 Linux 上的 Docker 不同,Linux 上的 Docker 通常将容器和镜像存储在主机文件系统的 /var/lib/docker
目录中。
磁盘镜像文件在哪里?
要找到磁盘镜像文件,请从 Docker Desktop Dashboard 中选择 Settings,然后从 Resources 选项卡中选择 Advanced。
Advanced 选项卡显示磁盘镜像的位置。它还显示磁盘镜像的最大大小以及磁盘镜像实际占用的空间。请注意,其他工具可能会按最大文件大小(而非实际文件大小)显示文件的空间使用情况。
如果文件太大怎么办?
如果磁盘镜像文件太大,您可以
- 将其移动到更大的驱动器
- 删除不必要的容器和镜像
- 减小文件的最大允许大小
如何将文件移动到更大的驱动器?
将磁盘镜像文件移动到其他位置
从 Resources 选项卡中选择 Settings,然后选择 Advanced。
在 Disk image location 部分,选择 Browse 并为磁盘镜像选择一个新位置。
选择 Apply & Restart 使更改生效。
请勿直接在 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 部分包含一个滑块,允许您更改磁盘镜像的最大大小。调整滑块以设置较低的限制。
选择 Apply & Restart。
当您减小最大大小时,当前磁盘镜像文件将被删除,因此所有容器和镜像都将丢失。