Docker default bridge network not working in wsl2

Viewed 2117

I'm using ubuntu 20.04 running in WSL2 and docker had been running fine for months, but recently the containers can't connect to the internet when using the default bridge network (docker0).

If I run docker run --rm -it ubuntu (or the equivalent docker run --rm -it --network bridge ubuntu) and try to run apt update, for example, it gives errors like Temporary failure resolving 'archive.ubuntu.com'.

The command works on the host, as well as running the ubuntu container with the host network.

It also works if I create another bridge network and use it instead of the default bridge network:

host$ docker run --rm -it --network testnet ubuntu
container$ apt update
# works fine (testnet is a newly created bridge network)

I uninstalled docker, removed the /var/lib/docker folder, disabled and removed the docker0 network (that is created again when running docker) to no avail.

The following is the output after inspecting the default bridge network (docker0):

[
    {
        "Name": "bridge",
        "Id": "f3ea111de9f8fe4fdf1c99f4d0d30375670c936670e1adb858d0b2fed5a8fa28",
        "Created": "2021-06-30T23:56:06.4722514-03:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

And the following is the output after inspecting the newly created bridge network (testnet):

[
    {
        "Name": "testnet",
        "Id": "30df12d4c6ed702877e05a452ec9eca0ce28f2692da1faa5e095f10af55ab9a4",
        "Created": "2021-06-30T23:50:54.5929609-03:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

Output of docker info:

Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Build with BuildKit (Docker Inc., v0.5.1-docker)

Server:
 Containers: 13
  Running: 11
  Paused: 0
  Stopped: 2
 Images: 28
 Server Version: 20.10.7
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: d71fcd7d8303cbf684402823e425e9dd2e99285d
 runc version: b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 4.19.104-microsoft-standard
 Operating System: Ubuntu 18.04.5 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 6.101GiB
 Name: DESKTOP-UC50AJ0
 ID: 55M4:UMSV:7C22:UOUJ:EKST:IITV:LAOP:3MLX:4BM6:RUBX:6OSG:JYSC
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support

Is there a (non-hackish) way to solve this issue? (without changing the host dns resolution or something similar, because the host dns resolution works, as well non-default bridge networks, so changing the contianer DNS resolution should not be needed; what I want is to make the default bridge network behave like the others regarding dns resolution)

My guess is that is some of the options above that are different than the other bridge networks, or maybe some firewall rule that is blocking the docker0 subnet (or gateway).

I don't think it's one of the different options returned by docker network inspect bridge (compared to the other bridge network), tough, because I just tried to run docker run --rm -it ubuntu in a VirtualBox VM (using Vagrant) with Ubuntu 20.04 and then apt update inside the container worked, and in the VM the result and options of docker network inspect bridge are exactly the same than the one in WSL2 (except the id and creation date).

Update 2021-07-01

It seems I found the cause, the resolv.conf file inside the container that uses the default bridge network is the same as the one in the host (WSL2), and probably because of that it doesn't work. The resolv.conf file in the container with the custom bridge network is different and has the docker dns server ip (127.0.0.11).

Container that uses the default bridge network (doesn't work):

root@715f0729ac4f:/# cat /etc/resolv.conf 
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.17.176.1

Container that uses the custom bridge network (works):

root@3e0ebc04e390:/# cat /etc/resolv.conf 
nameserver 127.0.0.11
options ndots:0

Now I need to know why this is happening and how to solve it without having to explicitly update that file in all new containers (to make it behave just like it worked before).

For the time being, I run echo '{ "dns": [ "8.8.8.8", "8.8.4.4" ] }' | sudo tee /etc/docker/daemon.json and restarted the docker service, which solved the issue, now it's using the Google nameservers (and I can see them in the resolv.conf file inside the container), but I don't consider it as a proper solution, especially considering that it worked before without including 3rd party nameservers.

I think there is a better way to solve this issue, so I'm not including this solution as an answer.

1 Answers

I think I had the same issue. I ran into after removing docker desktop, which was working fine but my company doesn't want to pay for it, and installing it directly in WSL2. I can resolve addresses outside of a container, but not inside using the default bridge network:

# this works
curl -m 2 google.ca
curl -m 2 142.250.217.99
# this doesn't
docker run --rm -it curlimages/curl -m 2 google.ca
docker run --rm -it curlimages/curl -m 2 142.250.217.99

I'm using Windows 10, WSL2, Debian 10/Buster, and Docker v20.10.14 (not Docker desktop). This is what worked for me:

# !! first remove or set to false in /etc/docker/daemon.json: "iptables": false
sudo touch /etc/fstab
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
# restart docker daemon

I found the solution mentioned here: https://github.com/microsoft/WSL/discussions/4872

Related