Docker restart blocks forwarded ports from services running in WSL

Docker for Windows: 4.12.0
OS Version/build - Windows 11 Build 22000.918 running Ubuntu 20.04.4 LTS

It seems like whenever I restart Docker, my ssh server running in WSL stops forwarding the port to my host.

Steps to reproduce:

  1. Install SSH-server on WSL instance. Have it listen to non-default port, e.g. 12345
  2. Turn on SSH service
  3. Verify SSH is listening on port 12345 from WSL, i.e. netstat -anpe | grep "12345"
  4. Verify Windows is listening on port 12345, i.e. netstat -ano | find "12345"
  5. Restart Docker few times (sometimes happens on second restart or third restart)
  6. Notice that step 3 still works, but step 4 fails

Looks like something blocks the port forwarding from WSL to Windows on Docker restarts. I have to fully restart WSL and Docker for it to start working again.

Anyone else facing this issue and know a workaround? I tried submitting through official paid support but this issue was ignored

Strange. Restarting Docker should not affect an other service’s port. If it does, It could probably happen with something else, not just Docker. If I have to guess why Docker triggers this error, maybe because Docker changes the IP tables rules. Even if it is true, and this is the problem, it should be a temporary problem only. If it is not temporary, then maybe something on Windows side detects the unavailable port and disables port forwarding to that port permanently until you restart WSL.

When it happens, are you connected to WSL via SSH?
Have you tried to restart SSH instead of restarting WSL?

Not a solution, just a tip: When I wanted to be able to use SSH to connect to WSL, I configured SSH on Windows and changed the SSH shell in the “authorized_keys” for my SSH key to a command which executed “wsl -d mydistribution

As far as I know, WSL was not designed to run multiple services inside, although you can do that manually. So I always tried to run the absolutely necessary services in the WSL distributions and everything else on Windows.

Yes, this does not work

The problem with this solution is that once I go into WSL, I cannot run Docker Pull commands because it seems like the CredsStore is not available to that session? I am not sure. All I want is to be able to run Docker commands from a SSH terminal. Currently, my setup is running a container that lets me SSH into that container, then chaining that to SSH into the WSL host. Running SSH in WSL by itself does not work as the forwarded port is not connectable from any device outside of localhost, and as mentioned, running it on Windows does not let me run docker-compose pull because of the credentials issue.

I think I ignored your very first line:

and the topic category and thought you used only WSL without the Desktop. Sorry about that. So now some questions

  • How do you restart Docker? I guess you just restart Docker Desktop
  • When you restart WSL, how do you do that? Restarting Docker Desktop should restart its WSL distributions as well, but I may be wrong because this is something I have never tested.

I just click restart through Docker Desktop. For WSL, I stop Docker, then do wsl --shutdown, then I start wsl by launching another shell

Can you reproduce the issue with an other service or only with SSH?

How exactly do you do that and why do you need to SSH into the WSL host? I can only imagine some debugging purpose. If this happens only with this SSH, maybe we can find an other way to do what you wanted to do.

Yes, I tried using nc to listen to port 12345. Once restarting Docker, the issue occurred where the port was being listened to in WSL, but not on the Windows host.

I just have a command set to SSH from the container into the WSL host using its own public key and configuration. So once I SSH into the container, it automatically SSH’s me into WSL.

The purpose is so I can run Docker commands remotely. I want to be able to control Docker from my phone. This specifically means docker-compose, so something like Portainer isn’t ideal. This would also let me edit the compose file or check volumes, etc.

I meant with running for example:

docker run -d --name nginx -p 8080:80 nginx

not by running something in the WSL distribution which is special itself, and it is even more special in case of Docker Desktop.

Yeah Docker properly forwards ports on a restart. I run plenty of containers like that. But I need SSH running in WSL specifically. Unless there is another way to manipulate Docker Compose remotely

Yuo can control Docker if you mount the docker socket into the container. You can use the Docker SDK or create your own REST API service in a docker client container and let the REST API execute the docker command. I consider the second as a “B” plan if you don’t want to learn the SDK.

Of course you want to control Docker Compose, but Docker Compose is already an app that uses the Docker socket to control Docker. You can try the compose-go library which is behind Docker Compose or use the “B” plan again so you develop an API in your favorite language so the API can execute docker compose

The only reason I would try to get into the virtual machine is debugging. I would never run SSH nor anything else inside only in Docker containers. Anything else can lead to unexpected behavior

This seems like a very complicated workaround compared to just restarting WSL alongside Docker Desktop. I do appreciate your help though.

This is not a workaround, this is how it should be done. This is how other tools are controlling Docker using the socket. You are trying to use Docker Desktop in a way it was not designed to be used and cannot be supported. You found one problem with it for now, but you can have more that you don’t know about yet.

In the beginning I suggested to SSH into Windows and use the wsl command to get inside the VM. You don’t actually need to log in to any WSL distribution. The easiest way would be to use the docker and docker compose commands from Windows. If you prefer to use bash, you can use Git Bash or something like that to run the bash script without WSL.