written by
Just4test

Docker Desktop的挂载性能损失

1 min read , April 18, 2020

Docker Desktop的挂载性能损失

我的工作机是Mac,最近的工作是在容器内运行maven构建。为了缓存包,我把maven的本地仓库.m2目录放在本机磁盘中,并挂载到容器中。然而构建过程极为缓慢,本来是分钟级别的构建过程花了一个多小时。

Docker Desktop中的容器其实是跑在了虚拟机里面,Mac下是VirtualBox,Win下是Hyper-V。然后卷映射这个功能,就是虚拟机的目录映射。这种映射进行连续读写比如大文件拷贝还行,但小文件处理速度要慢得多。maven构建需要大量的小文件读写,在Mac下比Linux下性能损失严重。

Docker官方注意到了这个问题,并提供了解决方案:使用cached或者delegated开启缓存,此特性仅支持Docker Desktop for Mac,在Docker CE Edge 17.04 中可用。我Mac上的Docker Desktop是2.2.3 edge版本,Engine 19.03.8。我运行了以下测试:

echo 测试原生性能
docker run --rm alpine time dd if=/dev/zero of=/tmp/test.dat bs=1024 count=100000
echo 测试挂载卷性能(consistent,默认)
docker run --rm -v `pwd`:/tmp alpine time dd if=/dev/zero of=/tmp/test.dat bs=1024 count=100000
echo 测试挂载卷性能(cached)
rm test.dat
docker run --rm -v `pwd`:/tmp:cached alpine time dd if=/dev/zero of=/tmp/test.dat bs=1024 count=100000
echo 测试挂载卷性能(delegated)
rm test.dat
docker run --rm -v `pwd`:/tmp:delegated alpine time dd if=/dev/zero of=/tmp/test.dat bs=1024 count=100000

然而结果并不理想,是否指定启用缓存并没有显著差异,原因未知。多次测试结果并不稳定,可能是这台Mac配置较低。挂载目录比直接读写慢大概50-100倍。

Windows平台也有类似的问题,而且并不支持上述缓存特性。不过Docker Desktop可以在启用了WSL2的系统上使用WSL2代替Hyper-V虚拟机,可以得到一定性能提升。测试结果如下(在第三个docker run前从WSL2切换到了Hyper-V):

多次测试结果相当稳定。基于WSL2时,测试消耗了13.2秒。相比基于Hyper-V的30.8秒性能有显著提升。然而即使是WSL2,也比不使用卷慢47倍。

我目前未能很好地解决该问题;也许可以考虑直接运行一个Linux虚拟机。

Update:通过将原本的挂载目录改为使用命名卷避开了这个问题。使用命名卷后,无法在Mac的资源管理器中查看文件,但完全避免了性能损失。