Running Docker on top of Windows Subsystem for Linux 2 (WSL2) provides near bare-metal Linux performance for Windows workstations. However, because WSL2 relies on a virtualized Hyper-V network interface, DNS routing between the Windows host, the WSL2 utility VM, and nested Docker containers frequently breaks without warning.

You boot up a development stack or run a build step, and you are hit with:

Err:1 http://archive.ubuntu.com/ubuntu jammy InRelease Temporary failure resolving 'archive.ubuntu.com' W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/jammy/InRelease Temporary failure resolving 'archive.ubuntu.com' E: Some index files failed to download. 

Or inside an Alpine container:

$ docker run --rm alpine ping -c 2 google.com ping: bad address 'google.com' 

Below is the complete architectural breakdown of why this happens, how corporate VPNs black-hole Hyper-V packets, and 3 production-tested fixes.

The Network Architecture Breakdown

Here is what your packet traversal looks like across Windows 11, WSL2, and Docker:

flowchart TD subgraph Host["Windows 11 Host"] NIC["Physical Wi-Fi / Ethernet"] VPN["Corporate VPN Adapter<br/>(Cisco AnyConnect / GlobalProtect / Zscaler)"] WFP["Windows Filtering Platform (WFP)<br/>(Blocks Non-VPN Outbound UDP 53)"] end subgraph HyperV["Hyper-V NAT Switch Layer"] vSwitch["Hyper-V Virtual Switch<br/>Gateway Proxy: 172.x.x.1:53"] end subgraph WSL2["WSL2 Linux VM (Ubuntu)"] Resolv["/etc/resolv.conf<br/>nameserver 172.x.x.1"] Systemd["systemd-resolved Stub<br/>127.0.0.53:53"] end subgraph Docker["Docker Engine Namespace"] Daemon["dockerd (Strips 127.0.0.0/8)"] Fallback["Blocked Fallback:<br/>Public Google DNS 8.8.8.8"] EmbeddedDNS["User-Defined Bridge<br/>127.0.0.11:53"] end NIC --> vSwitch VPN -.->|Locks down network| WFP WFP -.->|Drops packets from| vSwitch vSwitch --> Resolv Resolv --> Systemd Systemd --> Daemon Daemon --> Fallback Daemon --> EmbeddedDNS Fallback -.->|Fails: Temporary failure in name resolution| Docker

Why It Fails Under the Hood

  1. Hyper-V NAT & VPN Black Holes: In standard WSL2 NAT mode, Windows sets /etc/resolv.conf to the virtual switch IP (172.x.x.1). When corporate VPNs (Cisco AnyConnect, GlobalProtect, Zscaler) connect, strict Windows Filtering Platform (WFP) rules drop untracked Hyper-V interface packets.
  2. Docker Loopback Stripping: Modern Ubuntu WSL2 distros bind DNS to 127.0.0.53 (systemd-resolved). Inside a container namespace, 127.0.0.1 routes to the container itself. Docker detects this and strips all loopback addresses, falling back to hardcoded Google DNS (8.8.8.8). If your corporate network or firewall blocks raw outbound UDP 53, container DNS immediately hangs.
  3. Alpine musl libc A/AAAA Race: Alpine containers issue parallel A (IPv4) and AAAA (IPv6) queries over concurrent UDP sockets. If the Hyper-V NAT bridge drops or delays IPv6 responses, musl aborts with bad address.

Solution 1: Explicit Upstream DNS in Docker Daemon (Fastest)

If you use standard WSL2 NAT mode and don't need complex VPN tunneling, instruct Docker Engine to query known reachable DNS resolvers directly:

Create or edit /etc/docker/daemon.json inside your WSL2 terminal:

sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json << 'EOF' { "dns": ["1.1.1.1", "8.8.8.8"] } EOF 

Enterprise tip: If your workplace blocks public DNS, replace "1.1.1.1", "8.8.8.8" with your company's internal DNS servers. You can find them in Windows PowerShell via:

Get-DnsClientServerAddress -AddressFamily IPv4 

Restart Docker daemon:

sudo systemctl restart docker # or if using SysV init: sudo service docker restart 

Verify container resolution:

docker run --rm alpine nslookup google.com 

Solution 2: Prevent WSL2 from Auto-Generating /etc/resolv.conf

To permanently prevent WSL2's /init process from overwriting /etc/resolv.conf on reboot:

  1. Update /etc/wsl.conf inside WSL2:
sudo tee /etc/wsl.conf << 'EOF' [network] generateResolvConf = false EOF 
  1. Replace the dynamic symlink with an immutable static file:
# Delete existing dynamic symlink sudo rm -f /etc/resolv.conf # Write static nameservers sudo tee /etc/resolv.conf << 'EOF' nameserver 1.1.1.1 nameserver 8.8.8.8 options edns0 ndots:1 EOF # Lock file to prevent systemd-resolved overwrite sudo chattr +i /etc/resolv.conf 
  1. Restart WSL2 from Windows PowerShell:
wsl.exe --shutdown 

Solution 3: Windows 11 Mirrored Mode & DNS Tunneling (The Ultimate VPN Fix)

If you are on Windows 11 (build 22H2 / 23H2+ with WSL 2.0.0+), Microsoft introduced Mirrored Networking and DNS Tunneling.

Instead of routing raw UDP packets across a virtual Hyper-V NAT switch, WSL2 mirrors Windows network adapters directly and intercepts DNS queries via virtualization socket APIs, executing them through the Windows host network stack.

Implementation:

  1. Open or create %USERPROFILE%\.wslconfig in Windows:
[wsl2] networkingMode=mirrored dnsTunneling=true autoProxy=true 
  1. Restart WSL2 from an elevated PowerShell terminal:
wsl.exe --shutdown 
  1. Check Hyper-V Firewall Settings: Mirrored mode delegates network traffic to the Hyper-V firewall. Ensure outbound traffic is permitted:
Get-NetFirewallHyperVVMSetting -PolicyStore ActiveStore 

If DefaultOutboundAction is Block, allow it:

Set-NetFirewallHyperVRule -DisplayName "Allow WSL2 Mirrored Outbound" -Direction Outbound -Action Allow 

Start WSL2 and test container connectivity:

docker run --rm alpine ping -c 2 google.com docker run --rm ubuntu:22.04 apt-get update 

Fix for Alpine Linux Containers (musl libc)

If Ubuntu containers resolve DNS fine but Alpine-based images (alpine, node:alpine, python:alpine) still fail with ping: bad address, pass query serialization flags:

In docker run:

docker run --rm \ --dns-opt="single-request-reopen" \ --dns-opt="ndots:1" \ alpine ping -c 2 google.com 

Or inject it into your Alpine Dockerfile:

FROM alpine:3.19 RUN echo "options single-request-reopen ndots:1" >> /etc/resolv.conf RUN apk add --no-cache curl ca-certificates 

Summary Checklist

Strategy Best For VPN Friendly Maintenance
/etc/docker/daemon.json Local development Moderate Very Low
Static /etc/resolv.conf General WSL2 fix Poor Moderate
Mirrored + DNS Tunneling Windows 11 + AnyConnect / GlobalProtect Best in Class Zero
Alpine dns_opt CI/CD & Alpine images N/A Low

For deep-dive diagnostic flowcharts and container performance notes, check out our full technical guide on GearFlow Lab.