내 잡다한 노트
호스트 컴퓨터와 도커 컨테이너간에 통신 과정 본문
리눅스 호스트에서 Docker 컨테이너로 IP 패킷이 전달될 때(호스트의 NIC는 192.168.* 대역, 컨테이너는 172.16.* 대역을 사용한다고 가정), 내부적으로는 리눅스 네트워킹 스택과 Docker가 설정한 가상 인터페이스(veth), 브리지(docker0 등), 네임스페이스가 관여하게 됩니다. 흐름을 단계별로 단순화하면 대략 다음과 같습니다.
1. 호스트 측에서 패킷을 생성 (출발지: 호스트 IP, 목적지: 컨테이너 IP)
- 어플리케이션/프로세스에서 172.16..(컨테이너 IP)로 패킷 전송
- 예: ping 172.16.0.2 와 같이 호스트가 컨테이너 IP로 직접 패킷을 전송하려고 할 때
- 커널 라우팅 테이블 확인
- 리눅스 커널은 “172.16.* 대역”으로 가는 경로(route)가 어디인지 확인합니다.
- Docker가 브리지(docker0 혹은 cni0 등) 인터페이스를 만들고, 172.16.*.*/172.17.*.*/172.18.*.* 같은 내부 네트워크를 할당해두었다면, 해당 네트워크 대역에 대한 경로가 docker0(또는 cni 브리지) 인터페이스 쪽으로 잡혀 있습니다.
2. 가상 브리지(docker0)와 veth 페어로 패킷 전달
- 패킷을 docker0 인터페이스로 송신
- 커널은 172.16.*.*로 라우팅되는 트래픽을 docker0 인터페이스(또는 비슷한 브리지 장치)로 내보냅니다.
- docker0는 일반 이더넷 브리지처럼 동작하여, veth(virtual ethernet) 페어 중 호스트 쪽 끝단을 연결하고 있습니다.
- veth pair (호스트 쪽 ↔ 컨테이너 네임스페이스)
- 컨테이너가 생성될 때, 호스트 네임스페이스 안에는 vethXYZ 같은 이름의 인터페이스가 생기고, 컨테이너 네임스페이스 내부에는 보통 eth0 같은 이름으로 이어진 veth의 반대쪽 끝이 존재합니다.
- 브리지(docker0)는 여러 veth pair(각 컨테이너마다 1개씩)를 “LAN 스위치”처럼 묶고 있는 형태입니다.
- MAC 주소/ARP 혹은 브리지 내부 룰
- 브리지 내부에서 “어떤 컨테이너에게 172.16.. 패킷을 전달해야 하는가?”를 MAC(또는 내부적으로 유지하는 veth 포트 정보)로 구분합니다.
- vethXYZ(호스트 쪽) ↔ eth0(컨테이너 네임스페이스 내부)로 실제 패킷이 전달됩니다.
3. 컨테이너 네임스페이스 내부로 패킷 도착
- 패킷이 컨테이너 네임스페이스의 eth0에 도달
- veth pair를 통해 컨테이너 내부 인터페이스(eth0)로 패킷이 들어옵니다.
- 이 시점에서 IP 목적지는 여전히 172.16.*.*이고, 컨테이너 네임스페이스가 해당 IP를 “자신의 IP”로 알고 있으므로 로컬로 처리합니다.
- 컨테이너 IP 스택 상위로 전달
- 컨테이너 커널 네임스페이스의 IP 레이어가 **“내 IP로 온 패킷”**이므로 소켓 레벨로 전달합니다.
- 컨테이너 내부의 어플리케이션(예: 웹 서버, 또는 어떤 프로세스)이 172.16..:PORT로 리스닝 중이었다면, 해당 프로세스가 패킷을 받아 응답을 처리합니다.
- 응답 패킷(컨테이너 → 호스트)
- 컨테이너가 응답을 보낼 때는 소스 IP 172.16.. → 호스트 IP(192.168.* 또는 127.0.0.1 등)로 패킷을 만들어 eth0(컨테이너 내부) → vethXYZ(호스트) → docker0 브리지 → 호스트 IP 스택 경로를 통해 전달됩니다.
- 호스트가 이 응답을 받아서 로컬 어플리케이션에 전달하게 됩니다.
4. 정리
- 호스트 라우팅: 호스트는 “172.16.*” 대역을 docker0 브리지 인터페이스로 보내도록 라우팅 테이블이 설정됩니다.
- 브리지( docker0 ): 실제 이더넷 스위치처럼 가상 인터페이스들(veth pairs)을 묶어, 해당 IP(172.16..)를 가진 컨테이너 veth로 트래픽을 전달합니다.
- veth pair: 호스트 네임스페이스와 컨테이너 네임스페이스를 연결해주는 가상 NIC 쌍입니다. 호스트 쪽 끝은 브리지에 붙고, 반대쪽 끝은 컨테이너 내부에서 eth0 등으로 잡힙니다.
- 컨테이너: 자체 네임스페이스에서 172.16.. IP를 “로컬 IP”로 사용하며, 패킷을 수신/송신합니다.
결국 호스트에서 “172.16..”로 보내는 패킷은,
- 호스트 커널 라우팅 → docker0 브리지로 전송
- 브리지가 해당 컨테이너의 veth를 찾아 내부로 전달
- 컨테이너 네임스페이스의 eth0 인터페이스에서 수신
이런 과정을 거쳐 컨테이너로 도달하게 됩니다.
'DevOps > docker' 카테고리의 다른 글
Docker에 데이터베이스를 넣는 것이 좋은 생각일까요? (0) | 2025.02.14 |
---|---|
docker stack이란? (0) | 2025.01.03 |
오버레이 네트워크 (0) | 2024.12.26 |
Docker buildkit 이란? (0) | 2024.12.26 |
도커 컨테이너와 VM의 차이 (0) | 2024.12.05 |