Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't connect to WSL2 localhost server from WSL2 docker container

I am running a simple web server on https://0.0.0.0:4000 (accessible also as https://local.phx-cd.shoepping.at:4000 with mapping to 127.0.0.1 in Ubuntu hosts file) on my WSL2 Ubuntu. I can connect to it from both Ubuntu and Windows host - so far so good. But additionally, in my Docker for Win with WSL2 integration, I run a selenium chrome container which is connecting and testing stuff on that web server (using bridge), but it can't connect to it!

I connected to the container and tried to curl to the web server - connection refused. Since I have dual boot on my computer, I tried to switch to my Linux distro, run web server there and selenium in Linux Docker and connection to the local web server worked. So I think it has something to do with the WSL2.

My docker-compose.yaml (I left out my selenium hub config)

selenium-chrome-local:
      image: selenium/node-chrome-debug:3.141.59
      restart: always
      ports:
        - 5901-5902:5900
      volumes:
        - /dev/shm:/dev/shm
        - ../../temp:/home/seluser/Downloads
      depends_on:
        - selenium-hub-local
      environment:
        - SCREEN_WIDTH=1920
        - SCREEN_HEIGHT=1080
      extra_hosts:
        - "local.phx-cd.shoepping.at:10.99.99.1"
      networks:
        - selgrid
        - dockerhost

 networks:
    selgrid:
    dockerhost:
      driver: bridge
      ipam:
        config:
          - subnet: 10.99.99.0/24

Let me know if you need more config. Thanks.

like image 731
Skocdopole Avatar asked Dec 16 '20 16:12

Skocdopole


Video Answer


2 Answers

Are you sure that the Ubuntu WSL2 instance is running bridged? By default, WSL2 instances run NAT'd (whereas WSL1 instances ran bridged). So, while yes, the Docker network is bridged, it still can't access the NAT'd WSL2 VM without some extra work.

I'm fairly sure that you are running into the root problem described in WSL issue #4150. If so, here are some things to try ...

Option #1 - Port forwarding to the WSL2 instance

There are several workarounds suggested in that Github issue, but the basics that would work for your case boil down to forwarding port 4000 from the Windows host interface to the WSL2 instance's private IP address. In PowerShell:

netsh interface portproxy delete v4tov4 listenport="4000" # Delete any existing port 4000 forwarding
$wslIp=(wsl -d Ubuntu -e sh -c "ip addr show eth0 | grep 'inet\b' | awk '{print `$2}' | cut -d/ -f1") # Get the private IP of the WSL2 instance
netsh interface portproxy add v4tov4 listenport="4000" connectaddress="$wslIp" connectport="4000"

Note that you'll need to do this after each reboot, or else set up a script that runs at logon as described in the Github issue (see this comment).

Option #2 - WSL1

I would also propose that, assuming it fits your workflow and if your web app runs on it, you can simply use WSL1 instead of WSL2. You can try this out by:

  1. Backing up your existing distro (from PowerShell or cmd, use wsl --export <DistroName> <FileName>
  2. Import the backup into a new WSL1 instance with wsl --import <NewDistroName> <InstallLocation> <FileNameOfBackup> --version 1

It's possible to simply change versions in place, but I tend to like to have a backup anyway before doing it, and as long as you are backing up, you may as well leave the original in place.

Possible Option #3 - socat forwarding or tunnel

While I haven't tested your particular use-case directly, I have played around with socat in WSL2 with success. From the looks of it socat could be used for port forwarding from WSL2 to (at the least) the Windows host (which would be accessible to the Docker container. See this comment and example on Github about a similar use-case as yours.

Possible Option #4 - WSL2 in bridge mode

The Github thread referenced above also has some details on how to enable bridge-mode on the WSL2 interface using Hyper-V. I believe this requires Windows 10 Professional or Enterprise. It also has to be done after each reboot, as with Option 1. Again, probably overkill for this case, if port forwarding or WSL1 can accomplish what you need.

like image 150
NotTheDr01ds Avatar answered Oct 10 '22 04:10

NotTheDr01ds


Run this command on PowerShell as Administrator:

Replace {#requiredWindowsPort} with the port that will be used in the browser

Replace {#requiredWSL2Port} with the port running in WSL2 you want to connect to.

netsh interface portproxy add v4tov4 listenport={#requiredWindowsPort}
listenaddress=0.0.0.0 connectport={#requiredWSL2Port}
connectaddress=$($(wsl hostname -I).Trim());
like image 39
tlejmi Avatar answered Oct 10 '22 05:10

tlejmi