Docker 在 WSL2 上非常慢。

93
在了解到在WSL2上运行Docker时的性能改进后,我一直在等待支持WSL2的Windows 10的官方发布。我更新了Windows和Docker,并打开了使用WSL2的Docker标志,希望能为在Docker容器中运行的Oracle数据库带来一些性能提升,但不幸的是,这个改变使容器和我的笔记本电脑的性能大幅下降。容器的性能大约慢了10倍,启动容器时我的笔记本几乎无法使用。似乎内存消耗完全耗尽了我的8GB内存,并开始进行大量的内存交换。有什么办法可以提高WSL2上Docker的性能,或者至少更好地了解我的设置有什么问题吗?
我的环境: - 处理器:Intel(R) Core(TM) i7-2620M CPU @ 2.70GHz,2个核心 - 安装的物理内存(RAM):8.00 GB - Microsoft Windows 10 Pro 版本 10.0.19041 Build 19041 - Docker 版本 19.03.8,构建 afacb8b

1
我认为需要您的硬件规格信息以及所有相关软件的版本。 - underscore_d
4
我也有这个问题,我有16GB的内存,但vmmem进程消耗了大部分内存。 - Glen
顺便提一下,这个问题在这里:https://github.com/microsoft/WSL/issues/4166。由于我们所有的wsl2用户最终都会搜索如何处理卡住的窗口... - Pavel Biryukov
类似的问题,但涉及大量内存,在构建期间。 - XedinUnknown
我最近从Linux切换回Windows,这样我就可以更轻松地使用专有软件。起初这是我的最大问题,所以我最终选择了在Ubuntu上进行双重引导。然后昨天我看到了这篇文章:https://www.createit.com/blog/slow-docker-on-windows-wsl2-fast-and-easy-fix-to-improve-performance/,总的来说,你需要做的是将你的docker可访问代码存储在WSL2中,然后运行`docker-compose up`。从那里开始,你就可以像在Linux操作系统中一样正常地访问正在运行的容器。 - ViaTech
在WSL2的Docker中使用8GB RAM的Oracle DB?你是疯了吗!对于这个问题有太多答案,但没有一个正确的。问题出在Windows上。移除它后问题应该就解决了。 - rzlvmp
10个回答

89

这来自于“vmmem”,它会尽可能地消耗资源。

要解决问题,只需进入您的用户文件夹:

C:\Users\userName

在此目录中创建一个名为.wslconfig的文件,您可以在其中配置WSL2可使用多少资源:

[wsl2] 
memory=900MB    #Limits VM memory in WSL 2 to 900MB 
processors=1    #Makes the WSL 2 VM use one virtual processors

现在关闭你的 Docker 并等待任务管理器中的 "vmmem" 关闭。

然后您可以重新启动 Docker,通常情况下 "vmmem" 不会超过您设置的限制(这里是 900MB)。 如果不起作用,请重新启动计算机。

希望对您有所帮助。


4
非常感谢您的回答。Docker 应该提供设置这个或类似东西的选项。这里是微软关于 .wslconfig 的文档供参考。 - Glen
6
使用.wslconfig文件可以减少资源消耗,但实际上会使容器本身比以前更慢。我想我只是没有足够的内存,不得不继续使用Docker而无法利用wsl2的优势。 - doberkofler
6
我发现通过 .wslconfig 限制内存可以极大地提高 Docker 的性能。如果没有限制,Docker 似乎会使用尽可能多的资源。将 Docker 限制在 memory=6GB 对于我的 16GB 机器而言,使用 Docker 变得更加流畅。最佳设置可能会取决于可用的 RAM 和你在 Docker 中做什么,但我猜想,在许多情况下将其设置为(相当多!)超过 500MB 可能是明智的选择! - Nick F
1
这个调整对我来说也产生了巨大的影响。在进行docker build期间编译程序时,Vmmem会消耗我机器上所有可用的CPU。当编译停滞不前时,我的机器实际上几个小时都无法响应,只能使用kill -9命令杀死docker进程。将memoryprocessors分别设置为系统可用量的一半后,相同的构建过程只需要约10分钟即可完成。谢谢! - Mike Jarema
1
在我的情况下,vmmem进程没有自行停止。当我执行wsl.exe --shutdown时,它最终停止了。 - Juan Calero
显示剩余4条评论

47

你的代码可能存储在类似于以下文件夹的Windows机器上...

C:\\Users\YourName\projects\blahfu

但是你正在WSL 2上使用Docker,这是一个不同的(Linux)文件系统。因此,当你进行Docker构建时,所有的代码/上下文都会从Windows文件系统复制到Linux文件系统,然后从那里复制到Docker容器中。这就是最耗时且非常慢的部分。

尝试将项目放到像这样的文件夹中...

/home/YouName/projects/blahfu

您应该会获得相当的性能提升。


8
@Andy:从技术上讲,你的方法是有道理的,但 WSL 的想法是在 Windows 上利用 Linux 的强大功能并具有灵活性,应该能够处理好性能问题。如果我们把所有东西都移到 WSL 文件夹结构中,那就值得怀疑了。 - srk
1
官方指南在这里:https://docs.docker.com/docker-for-windows/wsl/#best-practices - akauppi
1
@Andy 换句话说,你的解决方法(我不会称之为解决方案)是特定于 Linux 用户的(即少数人)。那些使用 Windows 的人则无法使用。 - gargoylebident
3
将代码库从 Windows 盘移动到 WSL 目录下,运行 Docker 构建,速度提升 10 倍! - Kaymaz
1
是的,@Andy,情况确实如此!非常感谢您提供的解决方案!我将我的项目移动到了Ubuntu WSL的/home/目录下,速度提高了10倍以上! - Bullwinkle
显示剩余10条评论

21

WSL容器将与Windows文件系统隔离。

基本思路是将源代码从Windows文件系统复制到WSL文件系统中。

从Windows中,您可以访问WSL容器并将项目复制到WSL容器中:

使用资源管理器导航到 \\wsl$

从该位置重建容器即可解决问题!


3
我不理解,请您详细说明您的评论。 - doberkofler
正如我在这里已经提到的,完整的数据库,包括所有数据文件,都存储在容器本身中,没有挂载任何Windows文件系统。 - doberkofler
好的,我们来看一下文档上说的:“docker run image-name : image-name可以是你本地机器上的一个Docker镜像[...]” 当你在其他计算机上运行你的镜像构建时,你仍然运行的是位于你机器上的镜像。那么问题来了,这个镜像存储在你的计算机上的哪里呢? - tooy
是的!完全正确!将它复制到WSL并在那里运行! :) - tooy
1
我无法复制任何东西 - 似乎是一个特殊的文件夹,只读。 - ESP32
显示剩余3条评论

12

如果实际的Docker容器数据存储在Windows文件系统(即NTFS)上,而不是存储在本地Linux文件系统上(无论Docker容器内容如何,这些内容可能已经基于Linux),那么我认为您会看到较慢的性能,因为您正在运行WSL并从挂载的WINDOWS文件系统(即/c/mnt/...)使用Docker容器。

如果您将Docker容器复制到WSL上的/usr/local/home/<username>/docker之类的位置,则可能会看到10倍的性能提升。

尝试一下,看看是否有效?


完整的数据库,包括所有数据文件,都存储在容器本身中,没有挂载的Windows文件系统。 - doberkofler
那些wsl文件存储在C:\中,对吗?如果是这样的话,由于程序文件等也存储在那里,它会使我的C驱动器很快变满。:'( - Fahmi
除了复制,我还需要更改docker-compose吗?即使更改了docker-compose路径,我的文件仍然无法复制到容器中。 - Claudio Ferraro
是的,这里有记录 https://docs.docker.com/desktop/windows/wsl/ - TrojanName

5
你需要编辑 "vmmem" 资源,只需在以下路径中添加 .wslconfig 文件即可:

C:\Users\<你的用户名>.wslconfig

使用 .wslconfig 配置全局选项。
Available in Windows Build 19041 and later

您可以将.wslconfig文件放置在您的用户文件夹的根目录下,路径为C:\Users\\.wslconfig来配置全局WSL选项。许多这些文件与WSL 2有关,请注意您可能需要运行以下命令:

wsl --shutdown

关闭WSL 2虚拟机,然后重新启动WSL实例以使更改生效。

以下是一个示例.wslconfig文件:

Console

Copy
[wsl2]
kernel=C:\\temp\\myCustomKernel
memory=4GB # Limits VM memory in WSL 2 to 4 GB
processors=2 # Makes the WSL 2 VM use two virtual processors

请查看此网址:https://learn.microsoft.com/zh-cn/windows/wsl/wsl-config


什么是“内核”路径?如何找到它? - shaik moeed
[wsl2] memory=4GB # 限制 WSL 2 中的虚拟机内存为 4 GB processors=3 # 让 WSL 2 虚拟机使用两个虚拟处理器 - xpredo
1
你是指 C:\Users<yourUserName>.wslconfig 还是 C:\Users\<yourUserName>\.wslconfig - David
当然,C:\Users<你的用户名>.wslconfig - xpredo

2

打开您的WSL2发行版(例如Ubuntu)并设置~/.docker/config.json文件。
您只需要更改以下内容:

{
  "credsStore": "docker.exe"
}

"credsStore": "desktop.exe" : 超慢(超过2分钟)
"credsStore": "wincred.exe" : 快速
"credsStore": "" : 快速

它的工作非常出色。


1
如果您正在使用VS Code,有一个名为“Remote-Containers: Clone Repository in Container Volume...”的命令,可以确保您拥有完全速度的文件访问。
文档中可以看到:
Repository Containers使用隔离的本地Docker卷而不是绑定到本地文件系统。除了不会污染您的文件树外,本地卷还具有在Windows和macOS上改进性能的额外好处。

1

正如Claudio所提到的,将以下行设置在wsl ubuntu服务器的~/.docker/config.json中,解决了我的问题。

{ 
   "credsStore": "wincred.exe"
} 

之前构建任何简单图像都需要5-10分钟,现在只需1-2秒即可完成。

缺点是:每次打开服务器都必须进行此更改。我尝试了https://github.com/docker/for-win/issues/9843中提到的所有解决方案,但对我来说都没有用。


0
问题在其他答案中已经清楚地表述出来,但解决问题的方法并不明确。
首先,你需要在Windows中找到Linux文件系统。你可以通过打开文件资源管理器并输入"Linux"来找到它。你可能会看到类似于docker-desktopdocker-desktop-dataUbuntu的文件夹。我点击了"Ubuntu",在/mnt/wsl/www下创建了一个"www"文件夹,并在其中创建了我的项目文件夹。
然后,我重新启动了Docker,但出现了一些找不到卷的错误。我不得不进入Docker > 设置 > 资源 > WSL集成,并启用"Ubuntu",然后重新启动Docker。
我还将Docker重置为出厂设置,但我不认为这是必要的步骤。
总之,现在它对我来说已经可以工作了,并且比以前快100倍。
如果你发现我的步骤中有任何不必要的地方,或者有任何改进意见,请留言。

0

我在Windows 2019容器主机上的Docker中遇到了这个问题。恢复一个在我的电脑上只需要5秒钟的操作,却需要超过10分钟的时间。后来我发现MsMgEng.exe(Defender)进程正在扫描dockerd.exe(Docker守护程序),导致CPU使用率达到了98%。

为了确定问题,你可以在进行非常缓慢的Docker构建时运行任务管理器。如果是Defender实时扫描,你会看到dockerd.exe进程的CPU使用率飙升。Defender基本上阻碍了Docker的构建!

我相信这只是Docker守护程序的问题,但我还将docker.exe和gitlab-runner.exe添加到了处理器排除列表中。处理器排除的神奇之处在于,你不必排除任何文件夹,它会自动避免扫描进程正在处理的任何文件夹。

13分钟的恢复已经成为过去式!问题解决了。你不需要在dotnet restore上使用任何特殊参数、条件或标志。


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