Docker桌面版 - 关于文件共享性能不佳的通知

70

当我的Docker容器启动时,我会收到以下通知:

Docker桌面版检测到您共享了一个Windows文件到WSL 2容器,这可能导致性能下降。点击此处获取更多详细信息。

enter image description here

我的问题是:

  1. 这是什么意思?
  2. 最佳实践是什么/应该如何避免?
  3. 如果消息已关闭或我已点击“不再显示”,如何获取此警告的详细信息?

如果需要,我很乐意分享Dockerfile或Docker-Compose设置,但我无法在SO上找到任何指向任何方向的信息,也无法通过谷歌搜索找到,因此我不确定从哪里开始。 我假设问题出在Dockerfile中,因为我们在那里运行COPY来移动一些文件。

Docker版本:Docker桌面版2.4.0.0(48506)社区版

操作系统:Windows 10专业版(版本10.0.19041)


1
Docker文档中有关于Docker Desktop WSL2的进一步说明。对于类似的MacOS性能问题,两个重要注意事项是:不要使用绑定挂载来挂载应用程序代码(只需完全删除该挂载并使用镜像中的代码)或数据库存储(命名卷可正常工作)。 - David Maze
1个回答

54
  1. 这个错误意味着从Linux容器访问Windows主机文件系统中的文件将比访问已经在Linux文件系统中的文件慢一些。从Linux容器访问Windows文件将像访问远程文件共享一样。

  2. Docker和Microsoft建议通过将源文件存储在WSL2发行版的文件系统中(您可以将其绑定到容器中)或构建包含所有所需文件的容器映像来避免此问题,而不是将文件存储在Windows文件系统中。

  3. 如果您点击了“不再显示”,则可以通过转到使用Docker和WSL 2进行开发来查看此消息的详细信息。

有关更多信息,请参见Docker for Windows最佳实践

  • 仅当原始文件存储在Linux文件系统中时,Linux容器才会接收文件更改事件(“inotify事件”)。例如,某些Web开发工作流程依赖于inotify事件以进行文件更改自动重新加载。
  • 当文件从Linux文件系统中绑定挂载时,性能要高得多,而不是从Windows主机进行远程操作。因此,避免使用docker run -v /mnt/c/users:/users(其中/mnt/c是从Windows挂载的)。
  • 相反,从Linux shell使用类似docker run -v ~/my-project:/sources <my-image>的命令,其中~由Linux shell扩展为$HOME。

Microsoft的比较WSL 1和WSL 2文章有一个完整的跨操作系统文件系统的性能部分,其开头段落说:

我们建议不要跨操作系统处理您的文件,除非您有特定的原因。如果您正在Linux命令行(Ubuntu、OpenSUSE等)中工作,请将文件存储在WSL文件系统中以获得最快的性能速度。如果您正在Windows命令行(PowerShell、命令提示符)中工作,请将文件存储在Windows文件系统中。

此外,Docker博客文章Docker Desktop:WSL 2最佳实践有一个“Awesome mounts performance”部分,其中提到:

你自己的WSL 2发行版和docker桌面应用程序都在同一个实用程序VM上运行。它们共享相同的内核、VFS缓存等。它们只是在不同的命名空间中运行,以便他们有独立运行的幻觉。Docker桌面应用程序利用这一点来处理来自WSL 2发行版的绑定挂载,而不涉及任何远程文件共享系统。这意味着当您在容器中挂载项目文件(使用docker run -v ~/my-project:/sources <...>)时,docker将传播inotify事件并共享与您自己的发行版相同的缓存,以避免反复从磁盘读取文件内容。
不过要小心:如果您挂载的是位于Windows文件系统中的文件(例如使用docker run -v /mnt/c/Users/Simon/windows-project:/sources <...>),您将无法获得这些性能优势,因为/mnt/c实际上是通过Plan9文件共享公开Windows文件的挂载点。
如果您希望主要的开发工作流程在Linux上,则所有这些建议都非常好。Docker希望您完全投入Linux容器。但是,如果您主要在Windows上工作,并且只想使用Linux容器进行特殊任务,那么单击“不再显示”就可以了。正如Microsoft所说,“如果您在Windows命令行中工作,请将文件存储在Windows文件系统中。”
我在Windows中运行我的主要开发文件夹,并将其绑定挂载到一个Linux容器中,该容器仅用于执行单元测试。因此,我的完整构建在Windows中运行,然后我在Windows中运行所有单元测试,最后在Linux容器中运行所有单元测试。在这种情况下,Linux绑定到我的Windows文件夹,对于从我的Windows卷加载和执行所需的DLL的“dotnet test”调用非常快且非常好。
对于那些认为容器必须在任何地方使用的人来说,这个设置可能听起来像异端邪说,但我喜欢容器用于应用程序部署。我并不确信您需要全力以赴并在容器内进行所有开发。我很满意Windows(和VS 2019)作为我的开发环境,然后我使用Linux容器进行应用程序测试和部署。因此,Windows/WSL2文件系统性能影响对我来说是最小的影响。

如果你不是全面使用Docker WSL 2模式,启用它是否有意义?我的意思是说,确切的好处是什么,难道你就不能继续使用Hyper-V吗? - terkel
1
那是一个完全不同的问题。 - Bill Menees
非常全面的回答!我赞同“慢速”绑定挂载对大多数人来说都可以正常工作,但如果您正在尝试从容器中运行服务器(特别是像mysql这样的数据库),如果在Windows主机上太慢,那么这是一个很好的开始解决它的地方(通过执行上述建议!)感谢Bill。 - Evan Morrison
@BillMenees 如果我们想在Windows上将容器保留在主机卷上,我们应该遵循什么步骤? - user15807010
我不确定你在问什么(因为上面的对话框意味着您的容器已经托管在Windows上),但这似乎是一个单独的顶级问题。也许你想要这个或者这个。 - Bill Menees
我感觉很蠢 -> 我仍然对这个答案感到困惑。希望能看到一个编辑,其中包括一个带有错误卷参数的Docker命令,以及更好/更高效的方法。例如,之前 => docker run -v ${PWD}:/src/code .... 之后 => ???? - Pure.Krome

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接