이 글의 목적은 Windows에서 Docker Desktop을 사용할 때 Hyper-V 가상 스위치와 WSL2 가상 네트워크가 서로 대역을 침범하여 발생하는 컨테이너 접속 불가, DNS 실패, VPN 동시 사용 시 단절 문제를 재현 가능하게 진단하고, 주소 대역을 재설계하여 안정적으로 재구성하는 절차를 현장에서 바로 적용할 수 있도록 정리하는 것이다.
1. 문제 개요: Hyper-V vs WSL2 vs Docker Desktop이 왜 충돌하는가
Windows에서 Docker Desktop은 내부적으로 가상 스위치와 NAT를 사용하여 컨테이너 네트워크를 구성하는 구조이다.
Hyper-V는 “Default Switch(기본 스위치)”와 사용자 정의 가상 스위치를 통해 VM 트래픽을 처리하며, WSL2 또한 “vEthernet(WSL)” 같은 가상 어댑터를 만들어 NAT 기반 네트워크를 구성하는 방식이다.
Docker Desktop은 백엔드가 WSL2이든 Hyper-V이든 간에 여러 가상 네트워크를 생성하며, 이때 흔히 172.16.0.0/12 또는 192.168.0.0/16 같은 사설 대역을 자동으로 잡는 경우가 많다.
조직 내 VPN, 사내망, 테스트 랩망도 같은 사설 대역을 사용하는 경우가 많아 “대역 중복(Overlap)”이 발생하기 쉽다.
대역 중복이 발생하면 Windows 라우팅 테이블에서 더 우선순위가 높은 경로로 패킷이 흘러가며, 결과적으로 컨테이너로 들어가야 할 트래픽이 VPN 또는 다른 vSwitch로 빠져나가 접속 불가가 발생하는 구조이다.
| 대표 증상 | 현상 설명 | 가장 흔한 원인 | 우선 적용 전략 |
|---|---|---|---|
| 컨테이너 포트가 간헐적으로 안 열림 | 재부팅하면 잠깐 정상, VPN 연결 후 다시 실패가 발생하다 | WSL2 NAT 대역 또는 Docker 네트워크 대역이 VPN/사내망과 중복되다 | Docker 대역 재설정 + WSL2 네트워크 모드 재검토를 하다 |
| DNS가 WSL2에서만 실패 | WSL2에서 nslookup, apt, pip가 실패하고 Windows는 정상이다 | WSL2 NAT 경로/방화벽/터널링 충돌, VPN 정책 충돌이 발생하다 | WSL2 mirrored 모드 또는 DNS 터널링 설정을 정리하다 |
| localhost/127.0.0.1 접근이 꼬임 | Windows↔WSL↔컨테이너 간 포워딩이 기대대로 동작하지 않다 | 네트워크 모드 혼용, 포트 프록시 체인 충돌이 발생하다 | WSL2 networkingMode를 통일하고 검증하다 |
| Hyper-V VM과 Docker가 동시에 통신 불가 | VM은 인터넷 되지만 컨테이너 통신이 죽거나 반대 현상이 발생하다 | Default Switch(ICS) 대역이 Docker/HNS 네트워크와 충돌하다 | Default Switch 의존을 줄이고 사용자 정의 스위치로 분리하다 |
2. 현재 상태 진단: 어느 대역이 누구 것인지 먼저 확정하다
2.1 Windows에서 가상 어댑터와 IP 대역을 확인하다
가장 먼저 “vEthernet(WSL)”, “vEthernet(Default Switch)”, “vEthernet(DockerNAT)” 또는 Docker Desktop 관련 어댑터가 어떤 IPv4 대역을 쓰는지 확인해야 한다.
아래 명령은 네트워크 어댑터별 IPv4 주소를 빠르게 나열하는 방법이다.
powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "Get-NetIPAddress -AddressFamily IPv4 ^ | Where-Object { $_.InterfaceAlias -like 'vEthernet*' -or $_.InterfaceAlias -like '*Docker*' } ^ | Select-Object InterfaceAlias,IPAddress,PrefixLength ^ | Sort-Object InterfaceAlias ^ | Format-Table -AutoSize" 추가로 라우팅 테이블을 확인하여 중복 대역이 어떤 인터페이스로 빠지는지 확인해야 한다.
route print 중복이 의심되는 대역(예: 172.16.0.0/12, 172.17.0.0/16, 192.168.0.0/16, 10.0.0.0/8)이 라우팅 테이블에 동시에 존재하는지 확인하는 것이 핵심이다.
2.2 Docker 네트워크 구성을 확인하다
Docker Desktop이 생성한 네트워크 목록을 확인하여 브리지/사용자 네트워크가 어느 대역을 쓰는지 확인해야 한다.
docker network ls 실제 서브넷을 확인하려면 inspect가 필요하다.
docker network inspect bridge docker network inspect host docker network inspect none 사용자 정의 네트워크가 많다면 전수 확인이 필요하다.
docker network ls -q | % { docker network inspect $_ --format '{{.Name}} {{range .IPAM.Config}}{{.Subnet}} {{end}}' } 2.3 WSL2 내부 IP와 게이트웨이를 확인하다
WSL2 내부에서 본인 IP가 어떤 대역인지 확인해야 한다.
wsl.exe -e bash -lc "ip -4 addr; echo '---'; ip route; echo '---'; cat /etc/resolv.conf" 여기에서 WSL2의 기본 게이트웨이와 DNS가 어떤 방식으로 들어오는지 확인이 가능하다.
3. 해결 전략: 정리 → 대역 재설계 → 재구성 순으로 진행하다
3.1 1단계 정리: 가상 네트워크 상태를 깨끗하게 만들다
대역을 바꾸기 전에 “죽은 네트워크 객체”가 남아 있으면 재부팅 후 다시 꼬이기 쉽다.
따라서 아래 순서로 정리를 수행하는 것이 안전하다.
- Docker Desktop을 완전히 종료하다.
- WSL2를 완전 종료하다.
- 필요 시 HNS 관련 서비스를 재시작하여 Windows 컨테이너 네트워크를 정리하다.
REM 1) WSL2 완전 종료를 하다 wsl --shutdown REM 2) Docker Desktop을 UI에서 Quit로 종료하다 REM 3) 선택 사항: 네트워크 서비스 재시작을 하다 powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "Restart-Service hns -Force; Restart-Service vmcompute -Force" 3.2 2단계 대역 재설계: 충돌 가능성이 낮은 주소 정책을 잡다
대역 재설계는 “겹치지 않는 대역을 선택하는 작업”이며, 가장 중요한 운영 원칙은 다음과 같다.
첫째, 사내망과 VPN이 자주 사용하는 대역을 피하다.
둘째, Docker가 자동 생성하는 네트워크 수를 고려하여 충분한 풀(pool)을 잡다.
셋째, WSL2와 Docker를 서로 다른 큰 블록으로 분리하다.
| 대상 | 권장 방식 | 예시 대역 | 설계 포인트 |
|---|---|---|---|
| Docker 사용자 네트워크 풀 | default-address-pools로 /24 단위 자동 할당을 하다 | 10.200.0.0/16에서 /24로 쪼개다 | 프로젝트별 네트워크가 늘어도 충돌을 줄이다 |
| Docker 기본 브리지(docker0 또는 Desktop 내부 브리지) | bip로 고정 브리지 IP를 지정하다 | 10.201.0.1/24 | 브리지 대역이 다른 풀과 겹치지 않게 하다 |
| WSL2 NAT 대역 | NAT 모드 유지 시 별도 블록으로 분리하다 | 10.250.0.0/20 | VPN과 겹치면 mirrored 모드 검토가 필요하다 |
| Hyper-V VM 네트워크 | Default Switch 의존을 줄이고 사용자 정의 스위치를 쓰다 | 외부 스위치 또는 내부 스위치+NAT | ICS 기반 랜덤 대역 변동 리스크를 줄이다 |
3.3 3단계 재구성 A: Docker Desktop 네트워크 풀을 변경하다
Docker Desktop은 “Docker Engine” 설정에서 daemon 설정 JSON을 직접 편집하는 방식이 표준이다.
목표는 Docker가 새 네트워크를 만들 때 사용할 “기본 주소 풀”을 바꾸고, 필요하면 브리지 IP도 고정하는 것이다.
3.3.1 Docker Desktop Docker Engine 설정에 적용할 예시이다
아래 예시는 사용자 네트워크를 10.200.0.0/16 블록에서 /24로 자동 할당하게 하고, 브리지 IP를 10.201.0.1/24로 고정하는 예시이다.
{ "bip": "10.201.0.1/24", "default-address-pools": [ { "base": "10.200.0.0/16", "size": 24 }, { "base": "10.202.0.0/16", "size": 24 } ] } 적용 절차는 다음과 같다.
- Docker Desktop을 실행하다.
- Settings로 이동하다.
- Docker Engine 탭에서 JSON을 편집하다.
- Apply 또는 Restart로 Docker Desktop을 재시작하다.
3.3.2 기존 네트워크를 정리하고 새 대역으로 재생성하다
테스트 환경이라면 아래처럼 미사용 네트워크를 정리하는 것이 빠르다.
docker network prune Compose를 사용 중이라면 프로젝트별 네트워크를 제거 후 재배포하는 방식이 일관되다.
docker compose down docker compose up -d 3.4 3단계 재구성 B: WSL2 네트워킹을 안정화하다
WSL2는 NAT 기반 네트워킹이 기본이며, 이 NAT 대역이 VPN 또는 다른 가상 스위치와 충돌하면 문제가 반복될 수 있다.
WSL2는 최근 Windows 11(22H2 이상)에서 mirrored 모드라는 대안을 제공하며, 환경에 따라 NAT보다 호환성이 좋아질 수 있다.
3.4.1 방법 1: WSL2 mirrored 모드로 전환하다
mirrored 모드는 Windows 네트워크 인터페이스를 WSL2에 “미러링”하는 방식이며, VPN/프록시/로컬호스트 연동에서 이점이 있을 수 있다.
다음 경로에 .wslconfig 파일을 생성 또는 편집하다.
C:\Users\사용자계정\.wslconfig 경로이다.
[wsl2] networkingMode=mirrored dnsTunneling=true autoProxy=true 적용을 위해 WSL2를 완전 종료 후 다시 실행해야 한다.
wsl --shutdown 3.4.2 방법 2: NAT 모드를 유지하면서 WSL2 NAT 대역을 변경하다
조직 정책상 mirrored 전환이 어렵다면 NAT 대역을 다른 블록으로 이동시키는 방식이 실무에서 자주 쓰이다.
WSL2 NAT 대역은 레지스트리에서 관리되는 값이 존재하며, 대역과 게이트웨이를 변경한 뒤 WSL2를 재시작하여 반영하는 방식이다.
- 레지스트리 편집기를 실행하다.
- 아래 경로로 이동하다.
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss 해당 위치에 WSL2 NAT 관련 값이 존재하는 환경이 있으며, 다음과 같은 키가 사용되는 경우가 있다.
- NatNetwork
- NatGatewayIpAddress
예시로 WSL2 NAT를 10.250.0.0/20, 게이트웨이를 10.250.0.1로 맞추는 구성은 아래와 같은 형태가 된다.
NatNetwork = 10.250.0.0/20 NatGatewayIpAddress = 10.250.0.1 변경 후 반드시 WSL2를 완전 종료하고 재기동해야 한다.
wsl --shutdown 3.5 3단계 재구성 C: Hyper-V Default Switch 의존을 줄여 충돌 빈도를 낮추다
Hyper-V Default Switch는 ICS 기반으로 동작하는 특성이 있으며, 환경에 따라 대역이 바뀌거나 예측이 어려운 경우가 있다.
따라서 안정성이 필요하면 VM 트래픽은 외부 스위치 또는 사용자 정의 내부 스위치로 분리하는 것이 운영에 유리하다.
3.5.1 VM을 외부(External) 스위치로 분리하다
가장 단순한 방식은 물리 NIC에 바인딩된 외부 스위치를 만들고 VM을 그 스위치에 연결하는 방식이다.
이 경우 VM은 사내 DHCP 정책을 그대로 따르므로 Docker/WSL2 NAT와 직접 충돌할 여지가 줄어드는 구조이다.
3.5.2 내부(Internal) 스위치+NAT로 랩망을 만들다
랩 환경에서 내부망을 고정 대역으로 쓰고 싶다면 내부 스위치에 고정 IP를 주고 Windows NAT를 구성하는 방식이 가능하다.
이 방식은 Default Switch의 랜덤성을 피하고, “내가 정한 대역”으로 VM을 운영할 수 있다는 장점이 있다.
REM 예시 흐름을 설명하는 수준의 명령이다 REM 실제 인터페이스 이름과 대역은 환경에 맞게 설계 후 적용해야 한다 powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "New-VMSwitch -Name 'LabInternal' -SwitchType Internal" powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "New-NetIPAddress -InterfaceAlias 'vEthernet (LabInternal)' -IPAddress 10.240.0.1 -PrefixLength 24" powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "New-NetNat -Name 'LabNat' -InternalIPInterfaceAddressPrefix 10.240.0.0/24" 4. 재구성 후 검증: “된다”가 아니라 “재현 가능하게 확인”하다
4.1 Windows에서 라우팅 중복이 제거되었는지 확인하다
route print에서 중복 대역이 사라졌거나, 최소한 Docker/WSL2/Hyper-V가 서로 다른 블록을 쓰는지 확인해야 한다.
route print 4.2 컨테이너 통신을 기본 테스트로 검증하다
간단한 웹 컨테이너를 띄워 Windows에서 접근하고, WSL2에서도 접근하여 양방향이 정상인지 확인하는 방식이 효율적이다.
docker run --rm -d -p 8080:80 --name nettest nginx REM Windows에서 확인하다 curl http://127.0.0.1:8080 REM WSL2에서 확인하다 wsl.exe -e bash -lc "curl -sS http://127.0.0.1:8080 | head" 확인 후 컨테이너를 정리하다.
docker stop nettest 4.3 VPN 동시 사용 시나리오로 재검증하다
실제 장애는 VPN 연결 후 발생하는 경우가 많으므로, VPN을 연결한 상태에서 동일 테스트를 반복해야 한다.
VPN 연결 시 route print에서 특정 대역이 새로 생기거나 메트릭이 바뀌는지 확인하는 것이 핵심이다.
5. 운영 팁: 재발 방지를 위한 실무 체크리스트를 적용하다
5.1 대역 정책을 문서화하고 고정값으로 운영하다
Docker default-address-pools, WSL2 네트워킹 모드, Hyper-V 스위치 정책을 한 번 정하면 운영 문서로 고정하는 것이 재발 방지에 유리하다.
5.2 “사설대역 충돌”을 선제 차단하는 대역 선택 기준을 두다
사내에서 흔히 쓰는 10.0.0.0/8 또는 172.16.0.0/12, 192.168.0.0/16 일부를 이미 사용 중이면 Docker/WSL2는 다른 블록으로 분리해야 한다.
대역 선택 시 “현재는 안 겹치지만 추후 VPN 정책이 바뀌면 겹칠 수 있다”는 리스크까지 고려해야 한다.
5.3 네트워크 객체를 무작정 삭제하기 전에 복구 경로를 확보하다
docker network prune, 서비스 재시작, 레지스트리 수정은 빠르지만 영향 범위가 크다.
따라서 변경 전 현재 상태를 텍스트로 저장해 두는 습관이 실무에 유리하다.
REM 변경 전 스냅샷을 남기다 ipconfig /all > C:\Temp\net_before.txt route print >> C:\Temp\net_before.txt docker network ls >> C:\Temp\net_before.txt FAQ
Hyper-V Default Switch 대역을 고정하면 해결되는가?
Default Switch는 ICS 기반 특성으로 인해 대역이 재부팅 등 조건에서 변동될 수 있는 환경이 존재하다. 따라서 “고정”만으로 근본 해결이 되지 않는 경우가 많다. 운영 안정성이 목적이라면 Default Switch 의존을 줄이고 외부 스위치 또는 내부 스위치+NAT로 분리 운영하는 것이 재발 가능성을 낮추는 방향이다.
Docker 대역만 바꿨는데도 WSL2에서 DNS가 계속 실패하는 이유는 무엇인가?
DNS 실패는 단순 IP 중복뿐 아니라 VPN의 DNS 강제, 프록시 정책, WSL2의 DNS 전달 방식과 충돌하여 발생할 수 있다. 이 경우 WSL2 mirrored 모드 전환 또는 dnsTunneling 설정을 함께 검토하는 것이 실무적으로 효과적이다.
default-address-pools에서 size를 24로 두는 이유는 무엇인가?
/24는 네트워크 하나당 IP 256개 수준으로 격리하기 쉬우며, 프로젝트별로 네트워크를 많이 생성해도 충돌을 줄이기 유리하다. 반대로 /16처럼 크게 잡으면 다른 사설망과 겹칠 확률이 올라가고, 라우팅 충돌 시 영향 범위가 커질 수 있다.
WSL2 NAT 대역 변경과 mirrored 전환 중 어느 쪽이 더 안전한가?
NAT 대역 변경은 기존 아키텍처를 유지하므로 변화 폭이 작다는 장점이 있다. mirrored는 VPN/프록시/로컬호스트에서 호환성을 개선할 수 있으나, 특정 네트워크 드라이버 환경에서 예외가 발생할 수 있다. 따라서 운영 환경에서는 NAT 대역 변경으로 먼저 안정화를 시도하고, VPN 연동 문제가 지속될 때 mirrored를 검토하는 접근이 실무적이다.
재구성 후에도 “재부팅하면 다시 꼬인다”는 현상이 남는 이유는 무엇인가?
이 현상은 대역 자체가 다시 자동 할당으로 돌아가거나, 조직 보안 정책이 레지스트리/설정을 덮어쓰거나, Docker Desktop 업데이트로 설정이 재적용되는 경우에 발생할 수 있다. 따라서 설정이 실제로 유지되는지 재부팅 후 ipconfig, route print, Docker 네트워크 대역을 반복 확인하는 절차가 필요하다.