docker / for-win

Bug reports for Docker Desktop for Windows
https://www.docker.com/products/docker#/windows
1.86k stars 290 forks source link

Unable to connect to WSL2 host IP after update to 2.1.6.0 #5167

Closed JoshuaCWebDeveloper closed 4 years ago

JoshuaCWebDeveloper commented 4 years ago

After updating to the WSL2 Backend on Docker Desktop 2.1.6.0, I am unable to connect to the WSL2 host from within the container using the ip address obtained from running ip route from within the container.

I understand that this is a bit of a generic issue; however, the below steps work fine using the WSL2 Tech Preview on Docker Desktop 2.1.0.0; after updating to the WSL2 Backend on Docker Desktop 2.1.6.0, they no longer work.

Diagnostic Id

3EE432E3-080A-4607-B654-B887F9447E4C/20191118202258

Steps to reproduce the behavior

  1. Update from Docker Desktop 2.1.0.0 to Docker Desktop 2.1.6.0
  2. Enable WSL 2 Engine
  3. Switch on WSL Integration Ubuntu-18.04
  4. Apply & Restart
  5. In WSL2 Ubuntu-18, run sudo nc -l 80 to listen for incoming traffic
  6. Confirm that this will receive foreign requests by connecting to it from Windows using your WSL2 VM ip address
  7. After confirming, run sudo nc -l 80 again
  8. docker build an image from provided Dockerfile
  9. docker run -d a new container using the image
  10. docker exec $CONTAINER ip route where $CONTAINER is the container from step 9
  11. docker exec $CONTAINER wget $IP where $IP is the default route ip address from step 10

Dockerfile

FROM  ubuntu:18.04
USER root
RUN apt update && apt install -y wget iptables iproute2 curl jq
CMD sleep 1000

Expected behavior

Step 8 would result in a successful connection to the WSL2 host, and the HTTP header would be outputted by the sudo nc -l 80 command.

Actual behavior

Step 8 results in: Connecting to $IP:80... failed: Connection refused.

Logs from running step 8

[12:31:08.122][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy >> HEAD /_ping\n"
[12:31:08.124][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy << HEAD /_ping (1.0003ms)\n"
[12:31:08.148][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy >> GET /v1.40/containers/b3/json\n"
[12:31:08.161][APIRequestLogger  ][Info   ] [938340a2] <Server start> POST http://unix/usage
[12:31:08.162][APIRequestLogger  ][Info   ] [938340a2] <Server end> POST http://unix/usage -> 200 OK (took 0ms)
[12:31:08.165][APIRequestLogger  ][Info   ] [fb40cb20] <Server start> POST http://unix/usage
[12:31:08.165][APIRequestLogger  ][Info   ] [fb40cb20] <Server end> POST http://unix/usage -> 200 OK (took 0ms)
[12:31:08.153][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy << GET /v1.40/containers/b3/json (5.0011ms)\n"
[12:31:08.156][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy >> POST /v1.40/containers/b3/exec\n"
[12:31:08.158][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy << POST /v1.40/containers/b3/exec (2.0057ms)\n"
[12:31:08.159][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy >> POST /v1.40/exec/73179f3c3bee42b445cbddd101f1c479a9945a2b3f1ecbd916449c6f0d4ca7e1/start\n"
[12:31:08.165][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="Upgrading to raw stream"
[12:31:08.225][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy << POST /v1.40/exec/73179f3c3bee42b445cbddd101f1c479a9945a2b3f1ecbd916449c6f0d4ca7e1/start (65.9982ms)\n"
[12:31:08.226][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy >> GET /v1.40/exec/73179f3c3bee42b445cbddd101f1c479a9945a2b3f1ecbd916449c6f0d4ca7e1/json\n"
[12:31:08.229][ApiProxy          ][Info   ] time="2019-11-18T12:31:08-08:00" msg="proxy << GET /v1.40/exec/73179f3c3bee42b445cbddd101f1c479a9945a2b3f1ecbd916449c6f0d4ca7e1/json (3.0052ms)\n"
[12:31:11.613][FeedbackWindow    ][Info   ] Open logs

Information

Windows Insider Fast Ring build: 19023.vb_release.191108-1432 Docker Desktop Edge channel version: 2.1.6.0 (40740)

simonferquel commented 4 years ago

Yes, this is an issue with the new backend, as docker runs in its own networking namespace instead of the wsl2 common network namespace. If you are running a tcp service on your host (or anything tcp based like http(s)), you should be able to access it via host.docker.internal: WSL2 forwards any TCP listener within wsl2 to the Windows side.

JoshuaCWebDeveloper commented 4 years ago

@simonferquel Thanks for getting back to me. However, I ultimately need something that is host agnostic, and my understanding is that host.docker.internal is something that only works on Windows and Mac hosts, but not Linux hosts (https://github.com/docker/for-linux/issues/264). What do you think would be the next easiest way to accomplish this? The best workaround in that ticket that I saw was the method I was trying to use here.

simonferquel commented 4 years ago

For now this is the only workaround we have, unfortunately. If it is an important request, we'll add a network bridge between wsl2 root namespace and docker desktop network namespace to allow ip routing.

JoshuaCWebDeveloper commented 4 years ago

Well... it is important for me, haha! That is, if I want to upgrade to the new docker engine; I'm currently still using 2.1.0, but would like to upgrade. But I guess you'll need to prioritize over the whole project.

Is adding the network bridge between the two namespaces something that would be a potential work around for me (albeit perhaps somewhat complicated)?

simonferquel commented 4 years ago

Actually no (after some thoughts). However something that should work is to pass the ip of wsl2 VM to the container as an env variable (hostname -I should do the trick iirc)

JoshuaCWebDeveloper commented 4 years ago

Okay, so to clarify: if calling hostname -i in my WSL2 VM returns 127.0.1.1, then calling wget 127.0.1.1 inside my container should successfully hit port 80 on my VM (assuming all of the stuff in my original report still applies)? I'll give that a try today or tomorrow when I have time to upgrade back to 2.1.6 again.

simonferquel commented 4 years ago

Capital -I should give you a non-loopback I'm address

JoshuaCWebDeveloper commented 4 years ago

Oh sorry, thought that was a lowercase L, haha. Capital I works.

da-mask commented 4 years ago

Apologies if this is the wrong place to share my problem. I'm trying to use Xdebug on a container running on WSL2 Linux container. I've tried setting host.docker.internal on xdebug.remote_host, but the only way I've managed to hit breakpoints is manually find the ip of WSL and set that as the remote_host value in the container.

ponnapz commented 4 years ago

if calling hostname -i in my WSL2 VM returns 127.0.1.1, then calling wget 127.0.1.1 inside my container should successfully hit port 80 on my VM (assuming all of the stuff in my original report still applies)?

Did this work? I'm in a similar situation but calling that IP from the container results in: can't connect to remote host (172.18.3.229): Host is unreachable

JoshuaCWebDeveloper commented 4 years ago

I haven't tried it recently, but did you see @simonferquel's correction below that comment?

Capital -I should give you a non-loopback I'm address

simonferquel commented 4 years ago

Easiest way to do it, is to expose the xdebug port of the container (with docker run -p) so that it is reachable on 127.0.0.1 on the windows host.

ponnapz commented 4 years ago

@JoshuaCWebDeveloper yes, I'm using the non-loopback ip

To clarify, I am able to talk to the container from windows and also from the container in WSL back to services in Windows. But what doesn't work is making requests directly to a service in WSL VM (ubuntu) (I get the error in my original post). One workaround I found was to have port forwarding setup in windows to the WSL VM.

marfillaster commented 4 years ago

Can confirm that ports opened within WSL2 are not reachable through host.docker.internal

Simple test:

wsl2@ubuntu$ ncat -l 9000 -k -c 'xargs -n1 echo'
wsl2@ubuntu$ curl localhost:9000
/
HTTP/1.1
Host:
localhost:9000
User-Agent:
curl/7.58.0
Accept:
*/*

wsl2@ubuntu$ docker run --rm byrnedo/alpine-curl curl -s host.docker.internal:9000

Edit: Turns out VSCode PHP Debug launch.json hostname just need to be set to 0.0.0.0

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "hostname": "0.0.0.0",
            "port": 9000,
            "pathMappings": {
                "/app": "${workspaceRoot}"
            }
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000,
            "pathMappings": {
                "/app": "${workspaceRoot}"
            }
        }
    ]
}
docker-robott commented 4 years ago

Issues go stale after 90 days of inactivity. Mark the issue as fresh with /remove-lifecycle stale comment. Stale issues will be closed after an additional 30 days of inactivity.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows. /lifecycle stale

docker-robott commented 4 years ago

Closed issues are locked after 30 days of inactivity. This helps our team focus on active issues.

If you have found a problem that seems similar to this, please open a new issue.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows. /lifecycle locked