내 잡다한 노트

호스트 컴퓨터와 도커 컨테이너간에 통신 과정 본문

DevOps/docker

호스트 컴퓨터와 도커 컨테이너간에 통신 과정

peanutwalnut 2025. 1. 25. 16:16

 

리눅스 호스트에서 Docker 컨테이너로 IP 패킷이 전달될 때(호스트의 NIC는 192.168.* 대역, 컨테이너는 172.16.* 대역을 사용한다고 가정), 내부적으로는 리눅스 네트워킹 스택과 Docker가 설정한 가상 인터페이스(veth), 브리지(docker0 등), 네임스페이스가 관여하게 됩니다. 흐름을 단계별로 단순화하면 대략 다음과 같습니다.


1. 호스트 측에서 패킷을 생성 (출발지: 호스트 IP, 목적지: 컨테이너 IP)

  1. 어플리케이션/프로세스에서 172.16..(컨테이너 IP)로 패킷 전송
    • 예: ping 172.16.0.2 와 같이 호스트가 컨테이너 IP로 직접 패킷을 전송하려고 할 때
  2. 커널 라우팅 테이블 확인
    • 리눅스 커널은 “172.16.* 대역”으로 가는 경로(route)가 어디인지 확인합니다.
    • Docker가 브리지(docker0 혹은 cni0 등) 인터페이스를 만들고, 172.16.*.*/172.17.*.*/172.18.*.* 같은 내부 네트워크를 할당해두었다면, 해당 네트워크 대역에 대한 경로가 docker0(또는 cni 브리지) 인터페이스 쪽으로 잡혀 있습니다.

2. 가상 브리지(docker0)와 veth 페어로 패킷 전달

  1. 패킷을 docker0 인터페이스로 송신
    • 커널은 172.16.*.*로 라우팅되는 트래픽을 docker0 인터페이스(또는 비슷한 브리지 장치)로 내보냅니다.
    • docker0는 일반 이더넷 브리지처럼 동작하여, veth(virtual ethernet) 페어 중 호스트 쪽 끝단을 연결하고 있습니다.
  2. veth pair (호스트 쪽 ↔ 컨테이너 네임스페이스)
    • 컨테이너가 생성될 때, 호스트 네임스페이스 안에는 vethXYZ 같은 이름의 인터페이스가 생기고, 컨테이너 네임스페이스 내부에는 보통 eth0 같은 이름으로 이어진 veth의 반대쪽 끝이 존재합니다.
    • 브리지(docker0)는 여러 veth pair(각 컨테이너마다 1개씩)를 “LAN 스위치”처럼 묶고 있는 형태입니다.
  3. MAC 주소/ARP 혹은 브리지 내부 룰
    • 브리지 내부에서 “어떤 컨테이너에게 172.16.. 패킷을 전달해야 하는가?”를 MAC(또는 내부적으로 유지하는 veth 포트 정보)로 구분합니다.
    • vethXYZ(호스트 쪽) ↔ eth0(컨테이너 네임스페이스 내부)로 실제 패킷이 전달됩니다.

3. 컨테이너 네임스페이스 내부로 패킷 도착

  1. 패킷이 컨테이너 네임스페이스의 eth0에 도달
    • veth pair를 통해 컨테이너 내부 인터페이스(eth0)로 패킷이 들어옵니다.
    • 이 시점에서 IP 목적지는 여전히 172.16.*.*이고, 컨테이너 네임스페이스가 해당 IP를 “자신의 IP”로 알고 있으므로 로컬로 처리합니다.
  2. 컨테이너 IP 스택 상위로 전달
    • 컨테이너 커널 네임스페이스의 IP 레이어가 **“내 IP로 온 패킷”**이므로 소켓 레벨로 전달합니다.
    • 컨테이너 내부의 어플리케이션(예: 웹 서버, 또는 어떤 프로세스)이 172.16..:PORT로 리스닝 중이었다면, 해당 프로세스가 패킷을 받아 응답을 처리합니다.
  3. 응답 패킷(컨테이너 → 호스트)
    • 컨테이너가 응답을 보낼 때는 소스 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..”로 보내는 패킷은,

  1. 호스트 커널 라우팅docker0 브리지로 전송
  2. 브리지가 해당 컨테이너의 veth를 찾아 내부로 전달
  3. 컨테이너 네임스페이스의 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