Microsoft MVP성태의 닷넷 이야기
개발 환경 구성: 715. Windows - WSL 2 환경의 Docker Desktop 네트워크 [링크 복사], [링크+제목 복사],
조회: 8078
글쓴 사람
정성태 (seongtaejeong at gmail.com)
홈페이지
첨부 파일
 

(시리즈 글이 7개 있습니다.)
개발 환경 구성: 713. "WSL --debug-shell"로 살펴보는 WSL 2 VM의 리눅스 환경
; https://www.sysnet.pe.kr/2/0/13650

개발 환경 구성: 715. Windows - WSL 2 환경의 Docker Desktop 네트워크
; https://www.sysnet.pe.kr/2/0/13659

Linux: 88. WSL 2 리눅스 배포본 내에서의 pid 네임스페이스 구성
; https://www.sysnet.pe.kr/2/0/13771

Linux: 89. pid 네임스페이스 구성으로 본 WSL 2 배포본의 계층 관계
; https://www.sysnet.pe.kr/2/0/13772

Linux: 90. pid 네임스페이스 구성으로 본 WSL 2 + docker-desktop
; https://www.sysnet.pe.kr/2/0/13773

Linux: 91. Container 환경에서 출력하는 eBPF bpf_get_current_pid_tgid의 pid가 존재하지 않는 이유
; https://www.sysnet.pe.kr/2/0/13774

개발 환경 구성: 729. WSL 2 - Mariner VM 커널 이미지 업데이트 방법
; https://www.sysnet.pe.kr/2/0/13779




Windows - WSL 2 환경의 Docker Desktop 네트워크

지난 글에서 다뤘듯이,

"WSL --debug-shell"로 살펴보는 WSL 2 VM의 리눅스 환경
; https://www.sysnet.pe.kr/2/0/13650

WSL 2 VM에서 네임스페이스를 분리시켜 실행한 "docker-desktop" 컨테이너가 있고, 다시 그것에서 분리해 "LinuxKit" 컨테이너를 실행하고, 다시 분리해 docker 관련 컨테이너들이 실행되는 것입니다.

따라서 실질적인 docker 데몬이 시작한 환경은 "LinuxKit"이고, 그 환경을 조사하고 싶다면, 예전 DockerDesktopVM에 대해서 썼던 바로 그 방식과 유사하게 진입할 수 있습니다.

// Getting a Shell in the Docker for Windows Moby VM
// https://www.bretfisher.com/getting-a-shell-in-the-docker-for-windows-vm/

c:\temp> docker run -it --rm --privileged --pid=host justincormack/nsenter1
~ # ps a | grep docker
   59 root      0:00 /usr/bin/runc run --preserve-fds=3 01-docker
   71 root      0:00 /usr/libexec/docker/docker-init /usr/bin/entrypoint.sh
  143 root      1:05 /usr/local/bin/dockerd --config-file /run/config/docker/daemon.json --containerd /run/containerd/containerd.sock --pidfile /run/desktop/docker.pid --swarm-default-advertise-addr=192.168.65.3 --host-gateway-ip 192.168.65.254
...[생략]...
16183 root      0:00 grep docker




LinuxKit 컨테이너의 네트워크 환경을 살펴볼까요? ^^

우선 그 전에 VM의 네트워크 환경이 있을 것입니다. 해당 VM은 Hyper-V의 "vEthernet (WSL (Hyper-V firewall))" 가상 어댑터로 "vSwitch (WSL (Hyper-V firewall))" 가상 스위치에 연결됩니다. 이후, 그 위에서 생성되는 리눅스 배포본들은 그 환경을 그대로 이어받아 사용하는데요, 그래서 VM의 ifconfig 결과docker-desktop 배포본의 ifconfig 결과는 같습니다.

하지만, LinuxKit 컨테이너 레벨에서는 달라지는데요, 우선, docker는 자신이 사용할 내부 가상 네트워크를 임의로 생성하는 것이 가능합니다. 실졔로 Docker Desktop을 설치하면 기본적으로 3개의 네트워크를 가지는데요,

C:\Windows\System32> docker network ls
NETWORK ID     NAME                       DRIVER    SCOPE
39115851b938   bridge                     bridge    local
29b1107e441f   host                       host      local
1650344b2376   none                       null      local

각각의 네트워크 구성을 "docker network inspect" 명령어로 정리하면 이렇게 나옵니다.

[bridge]
"Driver": "bridge",
"EnableIPv6": false,
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"

[host]
"Driver": "host"
(null)

[none]
"Driver": "null"
(null)

그리고 bridge 네트워크로 연결해 실행한 컨테이너에서 ifconfig 명령어를 수행하면 다음과 같이 나옵니다.

// docker에서 생성한 임의의 컨테이너에서 ifconfig 출력

# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ...[생략]...

이와 함께 LinuxKit 컨테이너에서 ifconfig 명령어를 수행하면 이런 결과가 나옵니다.

// LinuxKit 컨테이너에서 실행한 ifconfig 출력 정리

[cni0] inet addr:10.1.0.1  Bcast:10.1.255.255  Mask:255.255.0.0
[docker0] inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
[eth0] inet addr:192.168.65.3  Bcast:192.168.65.255  Mask:255.255.255.0
[lo] inet addr:127.0.0.1  Mask:255.0.0.0
[services1] inet addr:192.168.65.6  Bcast:0.0.0.0  Mask:255.255.255.255

하나씩 볼까요? ^^ 우선 "[cni0]"는 k8s를 함께 설치했을 때 나오는 것입니다.

그다음 "[docker0] inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0" 항목은 낯이 익은 IP 대역인데요, 바로 docker가 기본 구성한 가상 네트워크인 bridge입니다. 다시 말해, Windows Command Shell에서 "docker network create" 명령어를 수행하면 (윈도우가 아닌) LinuxKit 컨테이너 환경 내에서 가상 네트워크를 생성하는 것입니다. (참고로 bridge 네트워크를 추가하면 기본적으로는 172.18.0.1/16, 172.19.0.1/16 등으로 순차 생성됩니다.)

마지막으로 [eth0] 196.168.65.0/24 네트워크가 재미있는데요, 이 구성은 Docker Desktop for Windows의 "Resources" / "Network" 메뉴로 바꿀 수 있습니다. 그러니까, 그것의 기본값이 Docker subnet == "192.168.65.0/24"인 것이고, 해당 네트워크에서 "LinuxKit 컨테이너"의 가상 IP는 "192.168.65.3"이 됩니다.

또한, 위의 환경에서 host.docker.internal, gateway.docker.internal은 ping을 해보면 각각 다음과 같이 나옵니다.

host.docker.internal 192.168.65.254
gateway.docker.internal 192.168.65.1

문서에 따르면, 192.168.65.0/24 네트워크는 (순수) 리눅스 운영체제에서 docker를 호스팅하는 경우에는 만들지 않는다고 합니다. 그런 의미에서, 아마도 192.168.65.0/24는 컨테이너에서 (VM을 건너뛰고) 호스트 네트워크와 연결하기 위한 보조 수단으로써 제공하는 듯합니다. 사실, Docker Desktop은 개발자 친화적으로 만들어진 응용 프로그램이고, 개발자가 주로 머무르는 환경이 (docker를 띄우기 위해 필요한 VM이 아닌) 호스트 운영체제가 되기 때문에 그것과 좀 더 부드럽게 연동하기 위한 네트워크로써 필요했을 것입니다. 실제로 192.168.65.0/24 네트워크는 거의 사용 용도가 없는데요, 제가 찾은 유일한 용도는 docker container 내부에서 "host.docker.internal (192.168.65.254)" 주소가 윈도우 호스트로 연결된다는 점입니다.

// 윈도우 호스트 측에 IIS 서비스를 설치했다면, docker run으로 띄운 컨테이너에서 IIS 80 테스트 가능

C:\temp> docker run -it --rm ubuntil
root@8091c139af60:/# curl host.docker.internal
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...[생략]...
<body>
<div id="container">
<a href="http://go.microsoft.com/fwlink/?linkid=66138&amp;clcid=0x409"><img src="iisstart.png" alt="IIS" width="960" height="600" /></a>
</div>
</body>

// 위의 "ubuntil" 이미지는 아래의 dockerfile 구성으로 "docker build -t ubuntil ." 명령을 실행해 생성한 이미지라고 가정.
// FROM ubuntu:latest
// RUN apt-get -y update && apt-get -y install net-tools

재미있는 점은, 윈도우의 VM으로 인해 필요하게 된 네트워크이고, host.docker.internal이 윈도우 호스트 측에 매핑된 것인데 그 과정이 필요 없는 리눅스 환경의 docker에서도 해당 DNS를 쓰고 싶다는 요청이 역으로 발생한 듯합니다. 그래서 리눅스의 경우에는 "--add-host=host.docker.internal:host-gateway" 옵션을 적용해 컨테이너를 실행했을 때 host.docker.internal에 대한 이름 풀이가 호스트 측으로 가능해집니다.

혹시 위의 설명 외에 192.168.65.0/24 네트워크에 대한 구체적인 용도를 아시는 분은 덧글 부탁드립니다. ^^




참고로 지난 글에서,

Visual Studio로 개발 시 기본 등록하는 dev tag 이미지로 Docker Desktop k8s에서 실행하는 방법
; https://www.sysnet.pe.kr/2/0/13645

hostPath를 "/run/desktop/mnt/host/c/temp/WebApplication1" 같은 식으로 지정했었는데, 실제로 이 경로는 "LinuxKit 컨테이너"에서 확인할 수 있습니다.

// LinuxKit 컨테이너 내부에서 실행
// docker run -it --rm --privileged --pid=host justincormack/nsenter1

# ls -l /run/desktop/mnt/host
total 0
drwxrwxrwx    1 root     root          4096 Jun 11 23:02 c
drwxrwxrwx    1 root     root          4096 Jun  9 01:52 d
drwxrwxrwt    5 root     root           120 Jun 12 23:26 wsl
drwxrwxrwt    7 root     root           300 Jun 13 15:03 wslg

그런데, 사실 /mnt/host 경로도 존재하긴 합니다. 예상과는 달리 서로 link로 연결되지도 않았는데요,

# ls -l /mnt/host
total 0
drwxrwxrwx    1 root     root          4096 Jun 11 23:02 c
drwxrwxrwx    1 root     root          4096 Jun  9 01:52 d
drwxrwxrwt    5 root     root           120 Jun 12 23:26 wsl
drwxrwxrwt    7 root     root           300 Jun 13 15:03 wslg

반면 권한까지도 완전히 똑같은데, 왜? k8s의 hostPath에는 "/mnt/host"로는 연결이 안 되고 반드시 "/run/desktop"으로만 정상적으로 동작하는 걸까요? (혹시 아시는 분은 덧글 부탁드립니다. ^^)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 7/2/2024]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 166  167  168  169  170  171  172  173  174  175  176  177  [178]  179  180  ...
NoWriterDateCnt.TitleFile(s)
536정성태9/12/200732354.NET Framework: 97. WCF : netTcpBinding에서의 각종 Timeout 값 설명 [11]
535정성태9/11/200729810.NET Framework: 96. WCF - PerSession에서의 클라이언트 연결 관리 [5]
534정성태9/3/200725309개발 환경 구성: 29. VHD 파일 크기 줄이기
533정성태9/2/200728013개발 환경 구성: 28. CA 서비스 - 사용자 정의 템플릿 유형 추가
532정성태9/2/200730548개발 환경 구성: 27. AD CA에서 Code Signing 인증서 유형 추가 방법
531정성태9/2/200726288.NET Framework: 95. WCF에서의 DataTable 사용
530정성태9/1/200722779.NET Framework: 94. WCF 예외에 대한 시행착오
529정성태8/31/200725695.NET Framework: 93. WCF - DataContract와 KnownType 특성 [1]
528정성태8/30/200720348오류 유형: 47. VPC - 네트워크 어댑터 MAC 주소 중복 오류
527정성태8/30/200730428Team Foundation Server: 20. 잠긴 파일을 강제로 해제 [2]
526정성태8/29/200720323오류 유형: 46. VS.NET 2008 - ASP.NET 디버깅 : Strong name validation failed.
525정성태8/27/200722564VS.NET IDE: 54. VS.NET 2008 - 새롭게 도입되는 XSD Schema Designer
524정성태8/23/200740076오류 유형: 45. 요청한 작업은, 사용자가 매핑한 구역이 열려 있는...
523정성태8/16/200722717VS.NET IDE: 53. VS.NET 2008 - 서비스 참조 시 기존 데이터 컨테이너 DLL 사용
522정성태8/13/200726369VS.NET IDE: 52. VS.NET 2008 - WCF를 위한 디버깅 환경 개선
521정성태8/8/200726385.NET Framework: 92. XmlSerializer 생성자의 실행 속도를 올리는 방법 - 두 번째 이야기 [3]
520정성태8/7/200721587VS.NET IDE: 51. Visual Studio 2008 베타 2 설치
519정성태7/27/200727960오류 유형: 44. System.BadImageFormatException [2]
518정성태7/26/200728977오류 유형: 43. System.ComponentModel.LicenseException [1]
517정성태7/19/200717255개발 환경 구성: 26. VPC - 일반 사용자 계정으로 구동
516정성태7/19/200720379오류 유형: 42. TFS - Error loading menu: Index was outside the bounds of the array [2]
515정성태7/18/200728123오류 유형: 41. SSL 서버 자격 증명을 만드는 동안 심각한 오류가 발생했습니다.
514정성태7/14/200720816Team Foundation Server: 19. Orcas에서 개선되는 TFS 기능들
513정성태7/4/200731791.NET Framework: 91. Foreground Thread / Background Thread [1]
512정성태6/27/200721726오류 유형: 40. error PRJ0050: Failed to register output.
511정성태6/25/200729727.NET Framework: 90. XmlSerializer 생성자의 실행 속도를 올리는 방법 [2]
... 166  167  168  169  170  171  172  173  174  175  176  177  [178]  179  180  ...