使用 WSL 2 上的 Docker Desktop,如何查找和检查绑定安装的确切主机文件夹?

With Docker Desktop on WSL 2, how to find and inspect the exact host folder of a bind mount?

我的主要问题是:使用 docker compose on Docker Desktop with WSL 2,当使用主机路径是相对路径的绑定安装时,实际主机路径在哪里以及是什么在 docker 桌面后端使用的 WSL 发行版上?

以下部分有助于理解上下文、我搜索和理解的内容,并详细说明我的问题。

实际来源问题

我有一个 docker 组合配置和一个带有 Angular 应用程序的容器。项目内容位于Windows文件系统,docker compose使用bind mount相对路径

容器确实获得了初始内容,但它似乎永远不会更新:没有实时重新加载,(硬)刷新浏览器页面时没有更新的内容。

请注意,这是在 Windows 上使用 Docker 桌面,在从 Hyper-V 后端切换到 WSL 2 后。使用 Hyper-V,一切都按预期进行,只是速度慢得多(正如他们在文档中所述)。

我的调查

我真的搜索了很多...而且很生气,因为我走了很多路,总是卡得很厉害。

可能还有其他一些我什至不记得的事情,可能已经离最初的主题太远了。

我还查看了官方 Docker 文档页面,但没有找到这些详细信息。

我的下一步是直接阅读后端的源代码...

我的期望

对我来说真正务实的结果是能够让容器与本地 Windows 文件系统内容交互,而不是与我找不到的似乎是副本的内容交互。

作为奖励,我很想了解涉及哪些路径,以及使用哪些机制来绑定所有这些(例如,使用工作 Hyper-V 后端,我希望 Hyper-V 具体机制已被用于使虚拟化 docker 进程有可能向容器公开 Linux 路径,最终只是一种硬 link / 共享文件夹 - 从概念上讲 - Windows 文件系统文件夹)。因此,在 docker compose 的配置中,我看到了一个 host <=> container 路径映射,但是在 Windows 上确实有一个 windows host <=> linux host <=> container 映射,它似乎是 windows host <=> linux host 映射Hyper-V 和 WSL 2 之间的行为不同,我无法找到 linux host 路径。

如果所有这些都可以得到 link 文档的支持(最好是 reference/official),它将使它 PERFECT.

但是,实际上,找到第一点的解决方案已经非常有帮助了。

我的问题是确认 Docker 实际使用什么路径作为 WSL 2 上的主机路径确实仍然存在,但现在更多的是出于好奇而不是必要(下面的解释)。

但是,我越来越猜测 运行 将 Windows 路径设置为 docker-desktop 发行版中的 /mnt/<my-absolute-path-here>

免责声明和上下文回顾

以下所有信息都没有回答我最初的问题,但希望它可以帮助其他人了解我调查期间涉及的主题。抱歉,如果这个问题在技术上 off-topic,但是当我开始在我的初始描述中提供上下文时,我也不小心引入了这些主题。

现在,回到我试图解决的最初问题:ng serve 提供的 Angular 应用程序没有显示包含更新内容的文件,因此 non-working live-reload 甚至通过浏览器刷新。

我的第一次验证:一个简单的文件服务器

因此,我构建了我能想象到的最小的服务器,运行 它在 Docker 内,并在某个文件夹上绑定安装,我将在其中更新我所服务的文件。当再次调用服务器时,它会给我更新的文件。

第一个结论:不是文件内容不更新的问题,是变化检测和缓存的问题

这里的假设:虽然 ng serve live-reload 功能在文件更改检测不起作用的情况下会不经意地起作用,但我怀疑后者也被用作缓存构建的真实来源,并且因此,重新加载浏览器页面不能强制使用更新后的文件内容进行重建。

我的第二次验证:运行chokidar

所以我构建了另一个小型服务器,返回 chokidar 在通过绑定安装公开的文件夹上捕获的事件列表。

在 Windows 端更新文件时,它没有检测到任何文件更改。但是,如果我从 WSL 2 shell 更改文件,它会被检测到。

第二个结论:虽然 Windows 和 WSL 2 最终都针对相同的文件,但这些文件的 API 的工作方式并不相同,具体取决于交互方和他们在一起。

解决方法和下一步调查

对于那些像我一样想要为 Angular 应用程序工作或使用任何文件更改检测库的人,这里有一个解决方法:使用轮询.

  • 对于Angular:使用--poll选项,查看serve and build命令文档
  • 对于 chokidar 或其他库:激活任何轮询选项(chokidar 有一个 here),否则你就没有办法解决这个问题

现在,在没有解决方法的情况下高效地完成这项工作仍然是我的目标之一,所以我将尝试了解如何在 Windows 端继续编辑内容,同时保持与申请也在 Windows 方面 运行ning。

参考资料

非常感谢 windows subsystem for linux - WSL filesystem miscoherency - Super User 中的回答。它解释了 Windows 和 WSL 2 之间文件系统的二分法。

虽然尚不清楚哪些有效,哪些无效,以及计划中的内容,但它确实对文件监视为何无效的问题给出了合理的解释。

现在,一些例子说明为什么不容易弄清楚会发生什么:

  • 修改日期在系统之间正确传播
  • WSL 2(inotify 我猜)在 Windows 端修改内容时没有捕捉到任何变化
  • 但是 Windows 确实会在 WSL 2 端修改内容时捕获更改

编辑 2022/04/04

好吧,我可以确认它链接到 inotify,这里有一些链接:

因此,虽然我仍然找不到完美的信息来源(比如官方文档甚至源代码),但我可以找到一些数据来证实之前的一些信息或假设。

策略

记住 Docker 是一个围绕核心 Linux API 构建的工具,例如 other container systems, I started to look at namespaces, and more specifically mount namespaces

获取信息的过程

因此,在 docker-desktop 发行版 (wsl -d docker-desktop) 上的 WSL 2 shell 实例上,过程如下:

  • 找到与您要获取其挂载信息的容器对应的进程 ID:为此使用 ps。我们将在下面将该值命名为 <pid>
  • 然后显示/proc/<pid>/mountinfo的内容:你可以使用cat
  • 每一行对应一个坐骑,包含所有需要的信息。找到与您的用例相关的行。例子:
    • for Portainer with standard installation,它使用命名卷:975 931 8:32 /version-pack-data/community/docker/volumes/portainer_data/_data /data rw,relatime master:3 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered
    • 对于我的绑定安装用例:1092 1070 0:56 /whatever/path/on/the/c/drive /container/path rw,noatime - 9p C:4 rw,dirsync,aname=drvfs;path=C:\;uid=0;gid=0;metadata;symlinkroot=/mnt/host,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8

信息解读

命名卷用例(应用于Portainer)

975 931 8:32 <b>/version-pack-data/community/docker/volumes/portainer_data/_data</b> <b>/data</b> rw,relatime master:3 - ext4 <b>/dev/sdc</b> rw,discard,errors=remount-ro,data=ordered 包含以下相关信息:

  • /version-pack-data/community/docker/volumes/portainer_data/_data是卷数据在Linux主机上的路径,相对于:
  • /dev/sdc,它指向 docker-desktop-data 发行版(您可以使用 findmnt -S /dev/sdc 进行检查,它给我们类似 /mnt/host/wsl/docker-desktop-data
  • 它暴露在容器内的 /data 上,正如创建它时所配置的那样

所以最终,它将 /data 映射到设备 /dev/sdc 上的 /version-pack-data/community/docker/volumes/portainer_data/_data,也可以从 /mnt/host/wsl/docker-desktop-data/version-pack-data/community/docker/volumes/portainer_data/_data.

访问它

但是我怀疑挂载命名空间直接使用设备,而不是它的挂载路径(我提供它只是为了“证明”它对应于 docker-desktop-data 发行版)。

绑定安装用例

1092 1070 0:56 <b>/whatever/path/on/the/c/drive</b> <b>/container/path</b> rw,noatime - <b>9p</b> C:\134 rw,dirsync,aname=drvfs;<b>path=C:\</b>;uid=0;gid=0;metadata; <b>symlinkroot=/mnt/host</b>,mmap,access=client,msize=65536,trans=fd,rfd=8,wfd=8:

  • /container/path 容器内指向...
  • /whatever/path/on/the/c/drive 在主机上,通过文件系统类型...
  • 9p,其中包含以下参数:
    • path=C:/: 所以 /whatever/path/on/the/c/drive 是相对于 C:/ Windows 驱动器
    • symlinkroot=/mnt/hostC:/ 驱动器安装在 /mnt/host 中,隐含在 /mnt/host/c

所以最终,主机路径再次直接从文件系统中使用,但它对应于 /mnt/host/c/whatever/path/on/the/c/drive

参考资料