Docker Desktop 热更新问题

面向 Docker Desktop for Windows,MacOS 应该有类似的解决思路。

Backgrounds

希望在 Windows 进行 Docker 环境下的 Vue 开发,同时在 Windows 本地进行文件管理。

在 Linux 的原生支持下,这并不成为问题。而在 Windows 中,Docker Desktop 使用 WSL2 作为后端,此时热更新是失效的,因为 WSL2 无法监听到从 Windows 中 mount 到 Linux 的文件系统的改变。

Solutions

尝试了数种方案,如图所示。方框表示 Windows 到 WSL2 的映射,绿色表示 -v 挂载双方。

从 Windows 直接挂载

如图 (a) 所示,无法热更新。

从 WSL2 挂载

如图 (b) 所示,WSL2 对 Windows 文件系统的映射路径为 /mnt,尝试将映射目录作为源目录挂载到 Docker,同样无法热更新。

值得一提的是,以上两种挂载方式可能导致 D:\App 变成一个 bind mount 目录,即从该目录下打开 WSL2 不再显示为 /mnt/d/App/,而是位于 /mnt/wsl/docker-desktop-bind-mounts/ 下的某个子目录。从该目录进行的文件操作会同步到 D:\App,谨慎操作。

实际上,在 Linux 下对 /mnt 进行操作是不推荐的。

从 WSL2 原生目录挂载

如图 (c) 所示,在 Linux 文件系统下进行挂载便解决了热更新问题。然而,在 Windows 下进行文件管理的需求尚未满足。考虑在 /mnt 与 Linux 原生目录间进行同步,有如下两种方案:

  • 编写同步脚本
  • docker-sync

最后还是没有采纳,拷贝副本再同步稍嫌麻烦,而且要考虑排除目录等。这是没有办法的办法。

原生目录挂载,并在 Windows 管理

第一次知道这个目录是可以正常操作的

1
\\wsl.localhost\Ubuntu-x.x\home\user

所以直接将文件下载 / 移动到该目录即可,然后挂载到 Docker. 有如下注意事项:

  • 除了原文件外,从 Windows 操作该目录会产生一个 <filename> :Zone.Identifier 文件。这个文件手动删除即可,目前看来没问题。
  • 在 VSCode 中 Security - Allowed UNCHosts 中配置 'wsl.localhost' 以在编辑器中打开目录
  • 发生目录变动时,VSCode 的文件树不会自动更新,需手动 ↺

验证,热更新成功。

References

  1. 关于 :cached 与 :delegated. 这两个挂载选项可能主要是与性能相关的,作为拓展阅读。
  2. Docker on wsl2, strange folder name - Docker Desktop - Docker Community Forums
  3. 解决 Windows Docker 环境下 Nextjs 热更新失效问题 - PaRaD1SE
  4. WSL 中出现 :Zone.Identifier 文件的原因和解决方法 - sulinehk blog