Closed slonopotamus closed 2 years ago
For the reference, here's how Docker Desktop works:
docker
CLI doesn't talk to them directlydocker
CLI always operates in default context that points at npipe:////./pipe/docker_engine
com.docker.proxy.exe
process that actually listens on npipe:////./pipe/docker_engine
desktop-linux
and desktop-windows
contexts, also pointing to proxy.Some logs.
This is how proxy is launched for Windows containers:
"C:\Program Files\Docker\Docker\resources\com.docker.proxy.exe" -windowsPipe=\\.\pipe\docker_engine_windows -dockerExe "C:\Program Files\Docker\Docker\resources\bin\docker.exe" -inject-hosts=true -native-api=true --windows-containers
This is how proxy is launched for Linux containers:
"C:\Program Files\Docker\Docker\resources\com.docker.proxy.exe" -windowsPipe=\\.\pipe\docker_engine_windows -wsl-distro docker-desktop -dockerExe "C:\Program Files\Docker\Docker\resources\bin\docker.exe
Neither proxy nor backend is running:
>docker info
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Build with BuildKit (Docker Inc., v0.6.3)
compose: Docker Compose (Docker Inc., v2.0.0)
scan: Docker Scan (Docker Inc., v0.8.0)
Server:
ERROR: error during connect: This error may indicate that the docker daemon is not running.: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/info": open //./pipe/docker_engine: The system cannot find the file specified.
errors pretty printing info
Proxy is running but backend is not (Linux containers):
>docker info
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Build with BuildKit (Docker Inc., v0.6.3)
compose: Docker Compose (Docker Inc., v2.0.0)
scan: Docker Scan (Docker Inc., v0.8.0)
Server:
ERROR: Error response from daemon: open \\.\pipe\docker_engine_linux: The system cannot find the file specified.
errors pretty printing info
Note that Linux dockerd is only listening "hosts":["unix:///var/run/docker.sock","unix:///run/guest-services/docker.sock"]
inside WSL2. It isn't yet clear who is listening on \\.\pipe\docker_engine_linux
and routing traffic into WSL2.
It isn't yet clear who is listening on \.\pipe\docker_engine_linux routing traffic into WSL2.
vpnkit-bridge.exe
does this. See "C:\Users\<user>\AppData\Roaming\Docker\log\host\vpnkit-bridge.exe.log"
. It is paired with vpnkit-bridge
running inside WSL.
It might be possible to open docker.sock
in AF_UNIX mode directly from Windows. See net.DialUnix
and https://github.com/moby/moby/issues/36442
Unfortunately, there's no way to pass custom transport to docker client: https://github.com/moby/moby/blob/v20.10.12/client/client.go#L120
See https://devblogs.microsoft.com/commandline/windowswsl-interop-with-af_unix/ It is very tempting to use AF_UNIX socket.
UPD: forget about AF_UNIX. It doesn't work in WSL2: https://github.com/microsoft/WSL/issues/5961
I'm currently working on docker-wsl-proxy
It is supposed to become the missing puzzle piece that converts Windows <-> WSL2 paths and routes docker requests into WSL2.
When docker-wsl-proxy is ready, the work will continue in linux-containers branch of current repo.
After several days of messing with docker-wsl-proxy, I start to think that using moby routes is a dead-end for several reasons:
ContainerDecoder
. Proxy runs on Windows, so doesn't have access to Linux implementation living in sysinfo_linux.go
systemrouter
. Several route implementations simply do not expect that server could fail.Client.NewClientWithOpts
is very restrictive and doesn't allow me to pass AF_UNIX transport. This could be implemented on Moby side (see https://github.com/docker/go-connections/pull/98), but that repo is nearly-dead, so god knows how many years it will take.New plan: we go one level lower and instead implement a HTTP proxy. Currently, it looks like the only place that requires paths conversions is container creation. We could intercept that API call in the proxy and rewrite JSON.
I suddenly understood that paths is not the only thing we need to do. We also need to support container port bindings to Windows host ports. This possibly can wait though.
HTTP proxy ended up being so much simpler: https://github.com/slonopotamus/docker-wsl-proxy/commit/7c75d2deb751ec6db2210537282a15e374d69910
Missing bits are:
First proof-of-concept that works across WSL boundary (docker server is inside, docker client is outside).
That's what was committed to main
branch:
https://user-images.githubusercontent.com/92637/153852434-f4518f98-fde2-4902-81f0-655df9c554f7.mp4
https://ksummersill.medium.com/creating-a-wsl-2-distro-from-scratch-4f52e3c0b881