rancher-sandbox / rancher-desktop

Container Management and Kubernetes on the Desktop
https://rancherdesktop.io
Apache License 2.0
6.03k stars 285 forks source link

docker in WSL is very slow compared to calling docker.exe #3867

Open jandubois opened 1 year ago

jandubois commented 1 year ago

Every docker command seems to take at least 6s in my VM, whereas the same command using docker.exe runs in less than 0.5s, and often less than 0.2s.

jan@DESKTOP-4992680:~$ time docker images
REPOSITORY          TAG       IMAGE ID       CREATED        SIZE
busybox             <none>    66ba00ad3de8   4 weeks ago    4.87MB
busybox             latest    0af8c5262529   4 weeks ago    4.14MB
tonistiigi/binfmt   latest    354472a37893   6 months ago   60.2MB

real    0m6.138s
user    0m0.091s
sys     0m0.697s

jan@DESKTOP-4992680:~$ time docker.exe images
REPOSITORY          TAG       IMAGE ID       CREATED        SIZE
busybox             <none>    66ba00ad3de8   4 weeks ago    4.87MB
busybox             latest    0af8c5262529   4 weeks ago    4.14MB
tonistiigi/binfmt   latest    354472a37893   6 months ago   60.2MB

real    0m0.462s
user    0m0.023s
sys     0m0.028s

jan@DESKTOP-4992680:~$ time docker context ls -q
default

real    0m5.914s
user    0m0.075s
sys     0m0.669s

jan@DESKTOP-4992680:~$ time docker.exe context ls -q
default

real    0m0.161s
user    0m0.015s
sys     0m0.001s

I can't think of any reason that would justify this slowdown; the command is just talking to a socket.

jandubois commented 1 year ago

For comparison, nerdctl doesn't have this problem:

jan@DESKTOP-4992680:~$ time nerdctl images
REPOSITORY    TAG    IMAGE ID    CREATED    PLATFORM    SIZE    BLOB SIZE

real    0m0.562s
user    0m0.003s
sys     0m0.054s

jan@DESKTOP-4992680:~$ time nerdctl.exe images
REPOSITORY    TAG    IMAGE ID    CREATED    PLATFORM    SIZE    BLOB SIZE

real    0m0.634s
user    0m0.023s
sys     0m0.002s
jandubois commented 1 year ago

@nunix pointed out that the difference is due to the executable being run from the Win32 file system. It runs at the proper speed when copied into the distro:

jan@DESKTOP-4992680:~$ cp "$(which docker)" docker
jan@DESKTOP-4992680:~$ time docker context ls -q
default

real    0m6.279s
user    0m0.000s
sys     0m0.968s

jan@DESKTOP-4992680:~$ time ./docker context ls -q
default

real    0m0.125s
user    0m0.012s
sys     0m0.073s

Still wondering why nerdctl doesn't seem to be affected the same way.

jandubois commented 1 year ago

Still wondering why nerdctl doesn't seem to be affected the same way.

Turns out our nerdctl "binary" is just a shim:

#!/bin/sh

if grep -q -i 'microsoft.*wsl' /proc/version; then
  exec /mnt/wsl/rancher-desktop/bin/nerdctl "$@"
[...]

So the actual binary is cross-mounted from the rancher-desktop distro.

We need to do this for all the Linux binaries on Windows, to get rid of the perf penalty.

jandubois commented 1 year ago

I don't know what is going on, but in a newly created VM, docker is slow even after copying it into /usr/local/bin while nerdctl continues to be fast:

jan@DESKTOP-4992680:~$ time /usr/local/bin/docker --version
Docker version 23.0.0-rd, build 59b762d

real    0m10.778s
user    0m0.401s
sys     0m2.625s

jan@DESKTOP-4992680:~$ time /mnt/wsl/rancher-desktop/bin/nerdctl --version
nerdctl version 1.1.0

real    0m0.346s
user    0m0.004s
sys     0m0.036s

Out of time to investigate further right now, but wanted to record that there is still some unknown part to this.

denyeo commented 1 year ago

I've been facing this problem. Somehow, docker copied to /usr/local/bin/ is still much slower than docker.exe at /mnt/c/Program Files/Rancher Desktop/resources/resources/win32/bin//docker.exe. It usually takes 3-4 seconds to do docker -v. WSL 1.2.5.0, kernel 5.15.90.1, Ubuntu 20.04.6.

I'm not sure what to do, but I'd prefer not to have to type docker.exe every time...

edit: I ended up creating a shim (like RD's nerdctl script shared above) to call docker.exe instead. Works nicely.

Kimi450 commented 3 months ago

A more concrete solution to what the folks have been describing above, the following worked for me (do it either once, or just put this line into your bashrc)

sudo ln -s "/mnt/c/Program Files/Rancher Desktop/resources/resources/win32/bin//docker.exe"   /usr/local/bin/docker 1>/dev/null 2>&1
jandubois commented 3 months ago

Note that docker.exe is the Windows version of the CLI, so will interpret volume mounts as Windows paths and not Linux path, so you may see some surprises there. Of course this doesn't matter if you don't specify any local path names as command arguments.