카테고리 없음
Docker Network 입문을 위한 기본 개념 정리 (1)
youngerjesus
2025. 6. 8. 20:51
질답 위주로 정리.
docker0 란 무엇인가?
- Docker 데몬이 부팅 시 자동으로 만드는 Linux 브리지.
- 디폴트 네트워크로 띄운 컨테이너만 docker0 를 사용한다고 알면 됨. `docker network create ` 로 만든 네트워크는 별도의 네트워크가 생성되는 것.
- 스위치처럼 L2 패킷을 중계하며, 컨테이너들을 하나의 가상 LAN에 연결한다. 기본 주소는 172.17.0.1/16
docker0 를 통해 통신이 이뤄지는 구조:
- (1) 컨테이너 내부 인터페이스 eth0 ←→ 호스트에 존재하는 veth 쌍
- (2) veth의 호스트 쪽 끝이 docker0 브리지에 “케이블”처럼 꽂힘
- (3) docker0은 스위치처럼 여러 컨테이너를 L2로 묶고, 호스트 외부 NIC(eth0)로 패킷을 포워딩
- (4) 브리지 밖으로 나가는 패킷은 호스트 iptables의 SNAT(MASQUERADE) 규칙으로 사설 IP → 호스트 IP로 변환되어 외부로 나갑니다.
Docker 데몬은 무엇?
- 리눅스/Windows에서 실행되는 백그라운드 서비스.
- 컨테이너 이미지 pull, 컨테이너 생성·삭제, 네트워크·볼륨 생성 등 모든 Docker API 요청을 처리
- 리눅스에서는 /var/run/docker.sock 유닉스 소켓을 열어 CLI(docker 명령)나 REST API 호출을 수신.
- 첫 기동 시 기본 네트워크(브리지 bridge / 인터페이스 docker0)와 기본 저장소( /var/lib/docker ) 등을 준비한다.
LAN 은 무엇?
- **동일 전송 매체(L2)**로 묶인 제한된 물리 범위(사무실, 데이터센터 랙 등)의 네트워크.
- 한 LAN 내부 장비들은 IP 대역(예: 192.168.0.0/24) 과 스위치(또는 브리지) 를 공유하며, L3 라우터 없이 직접 프레임 교환이 가능하다.
스위치는 무엇?
- 이더넷 프레임(MAC 기반)을 입력 포트 → 목적 MAC 이 있는 출력 포트로 전송하는 L2 장치
- MAC 주소 학습 테이블을 유지하여 브로드캐스트 최소화와 충돌 도메인 분리를 수행한다
- 리눅스 커널의 브리지 드라이버가 동일 기능을 소프트웨어로 제공한다
중계하다는 무엇?
- 한 네트워크 인터페이스에서 받은 패킷·프레임을 다른 인터페이스로 전달하는 행위.
- L2 프레임을 중계하면 “브리지/스위치 포워딩”, L3 패킷을 중계하면 “라우팅”이라 부른다.
도커에서 기본 주소 172.17.0.1/16 이 의미하는 건 뭐임?
- /16 CIDR은 넷마스크 255.255.0.0 (상위 16비트 네트워크, 하위 16비트 호스트)
- 네트워크 주소는 172.17.0.0. 사용 가능한 호스트 IP 범위는 172.17.0.1 ~ 172.17.255.254 (65 534개).
- Docker 기본 브리지(docker0)에 자동 할당되는 게이트웨이 IP 가 172.17.0.1이다.
eth0 와 veth 란? 이게 네트워크 통신에 어떤 역할?
- eth0 : (1) 물리 NIC 또는 (2) 네임스페이스 내부의 첫 가상 NIC 를 표시하는 표준 인터페이스 이름
- vethXXXX : veth pair 중 호스트 쪽 또는 컨테이너 쪽 끝점의 이름. 두 끝은 항상 서로 연결된 상태다
iptables 란 무엇? SNAT(MASQUERADE) 규칙은 무엇?
- 리눅스 netfilter 프레임워크용 CLI.• 패킷이 커널을 통과할 때 체인(PREROUTING, INPUT, FORWARD, POSTROUTING 등) 내 규칙을 순차 실행하여 필터링·NAT·계측 수행.• 명령은 모두 커널의 netfilter 테이블에 즉시 적용된다.
네임스페이스란?
- Linux 커널이 프로세스 그룹에게 특정 자원 집합을 독립적으로 가지도록 격리하는 기능.
- mnt(파일시스템 트리)·pid(프로세스 번호)·net(네트워크 스택)·uts(호스트이름)·ipc·user·cgroup 등 8가지가 존재하며, 각 타입별로 별도로 격리할 수 있다.
- network 네임스페이스: 독립적인 인터페이스 목록·라우팅 테이블·ARP 캐시·iptables 규칙을 가진다. 컨테이너마다 고유 net 네임스페이스를 부여하면, 서로 IP·포트 충돌 없이 별도 네트워크 스택을 운영할 수 있다.
이더넷 프레임은 MAC 주소 기반으로 데이터를 전달하는거인가?
- 이더넷 프레임은 목적지 MAC, 출발지 MAC, 페이로드 데이터로 구성
- 스위치·브리지는 프레임의 목적지 MAC을 보고 출구 포트를 선택한다.
- MAC 주소는 Layer 2 식별자이므로, 프레임 전달(브리지 포워딩)은 IP 라우팅보다 하위 계층에서 수행된다.
- 즉 MAC 주소 기반으로 전달되는게 맞다.
docker 를 이용해서 통신할 때 docker0 브릿지 보다 상단에 게이트웨이가 먼저 패킷을 받아서 처리하는 구조임?
- 컨테이너 → 외부로 나갈 때 경로 (docker0 브리지 vs 게이트웨이) 를 보자:
netfilter 란?
- Linux 커널에 내장된 패킷 처리 프레임워크. 패킷이 스택을 통과할 때 5개의 Hook(PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING)에서 필터·NAT·커넥션 추적을 수행한다.
- 사용 도구로 iptables(레거시), nftables(신규) CLI가 netfilter 테이블·체인을 조작한다.
- Docker Engine이 --iptables=true 기본 설정으로 동작하면• PREROUTING : DNAT(호스트포트→컨테이너포트)• POSTROUTING : SNAT/MASQUERADE(컨테이너IP→호스트IP)• FILTER : 컨테이너 트래픽 허용 규칙을 netfilter에 자동 삽입·삭제하여 컨테이너 네트워크를 투명하게 구성한다.
리눅스 내에서 도커 컨테이너를 사용한다고 했을 때 패킷이 전달되는 경로는? 주요 핵심 컴포넌트를 빠짐없이 설명.
- 전제
- (1) 컨테이너 네임스페이스 내부
1-A | 사용자 공간 프로세스가 send() 호출 → 커널이 TCP/UDP 세그먼트를 생성 → IP 헤더 구성 Src IP=172.17.0.2, Dst IP=8.8.8.8 |
1-B | 라우팅 선택컨테이너 netns 라우팅 테이블에는 default via 172.17.0.1 dev eth0 만 존재 → 게이트웨이 172.17.0.1 결정 |
1-C | ARP 확인게이트웨이 MAC 미존재 시 ARP Request를 브로드캐스트 → docker0(호스트 커널)이 ARP Reply → 캐시에 (172.17.0.1 → AA:BB:CC:DD:EE:FF) 저장 |
1-D | 이더넷 프레임 작성Dst MAC=AA:BB:CC:DD:EE:FF, Src MAC=veth-inner MAC → L2 프레임이 eth0(veth inner)로 송출 |
- (2) veth pair → 브리지 docker0 (호스트 L2)
단계 | 세부 동작 |
2-A | 프레임이 veth 링크를 타고 호스트 네임스페이스의 vethXYZ(outer) 인터페이스에 도착 |
2-B | vethXYZ 는 브리지 포트로 등록되어 있으므로 프레임은 docker0 브리지 포워딩 테이블로 진입 |
2-C | 프레임 목적 MAC이 브리지 자신의 MAC → “로컬 전달” 분기로 넘어가 IP 계층으로 상향 |
- (3) 호스트 L3 스택과 netfilter 경유
Hook 순서 | 핵심 처리 (표시는 Docker가 삽입한 규칙) |
PREROUTING / raw → mangle → nat | outbound 패킷에는 변환 없음 (DNAT X) |
Routing Decision | 커널 라우팅 테이블: 0.0.0.0/0 via 192.168.1.1 dev eth0 선택 → 출구=eth0, Next-hop IP=192.168.1.1 |
FORWARD / mangle → filter | -i docker0 -o eth0 ACCEPT 규칙을 Docker가 이미 설치 → 통과 |
POSTROUTING / mangle → nat | MASQUERADE -s 172.17.0.0/16 ! -o docker0 규칙 일치 → SNAT 수행 Src IP 172.17.0.2 ⇒ 192.168.1.100 (필요 시 Src Port도 변환) 커널 conntrack 테이블에 〈<172.17.0.2:12345>↔<8.8.8.8:53>, NAT=<192.168.1.100:45000>〉 레코드 생성 |
- (4) 호스트 NIC eth0 → 외부 네트워크
4-A | SNAT이 완료된 IP 패킷이 qdisc → 드라이버 → 물리 NIC eth0 로 전달 |
4-B | 호스트는 게이트웨이 MAC(라우터) 미보유 시 ARP Request 후 Reply 수신 → 프레임 전송 |
4-C | 라우터·인터넷 백본을 거쳐 목적지 8.8.8.8 에 도달 |
- (5) 응답 패킷 수신 (역방향)
Hook 순서 | 핵심 처리 |
NIC eth0 수신 | IP Dst=192.168.1.100, Src=8.8.8.8 |
PREROUTING / raw → mangle → nat | conntrack 항목 매치 → 역-SNAT Dst IP 192.168.1.100 ⇒ 172.17.0.2 Dst Port 45000 ⇒ 12345 |
Routing Decision | 172.17.0.2 는 docker0 브리지에 직접 연결된 사설 대역 → 출구=docker0 |
FORWARD | -i eth0 -o docker0 ACCEPT 규칙으로 통과 |
POSTROUTING | 외향 NAT 없음 |
브리지 docker0 | 포워딩 테이블에서 172.17.0.2 ↔ vethXYZ 매핑 → 프레임을 vethXYZ 로 전송 |
veth pair | vethXYZ → veth-inner (컨테이너 eth0) |
network namespace 에 대해서 보다 자세하게 설명.
ARP 지정이란?
- 동일 L2 네트워크에서 목적 IP → 목적 MAC 매핑을 얻는다.
- 절차:
- 컨테이너 → docker0 브리지 사이에서도 컨테이너가 게이트웨이 IP(172.17.0.1)에 대한 MAC을 알아내기 위해 ARP를 사용한다.
Linux 라우팅 테이블의 역할?
- 커널이 목적 IP를 어디로 보낼지 결정하기 위한 규칙 집합
- 각 규칙(라우트)에는
- 패킷이 IP 계층에 도달하면 커널은 Longest-Prefix-Match로 한 줄을 선택하고, 그 라우트에 지정된 인터페이스와 다음 홉을 사용해 전송한다.
NIC 와 이더넷 그리고 eth0 의 관계는?
- NIC (장치)가 Ethernet (프로토콜)을 사용하며, Linux는 그 장치를 eth0 같은 인터페이스 이름으로 노출한다.
- NIC: 네트워크에 물리적으로 연결되는 장치(유선, 무선, 가상 모두 포함)
- Ethernet: NIC가 주로 사용하는 링크 계층(IEEE 802.3) 규격·프레임 형식
- eth0: Linux에서 첫 번째 Ethernet-계열 NIC에 부여되는 기본 인터페이스 이름(최근 udev 규칙이 바뀌어 enp… 등이 될 수도 있으나, 컨테이너 내부에서는 Docker가 다시 eth0으로 이름 변경)
Gateway 의 역할은? 모든 호스트마다 게이트웨이가 있는건가?
- 로컬 서브넷을 벗어나는 IP 패킷을 받아 다음 네트워크로 전달하는 라우터
- 질문에 답하자면 모든 호스트가 게이트웨이를 가질 필요는 없다. 같은 서브넷 안에서만 통신하면 게이트웨이 없이도 동작
- 인터넷·다른 서브넷과 통신하려면 최소 하나의 게이트웨이(default route)가 필요
netfilter 의 스택이란? 스택을 통과할 때 5개의 Hook 이란? 필터 * NAT * 커넥션 추적이란?
- 패킷이 커널 네트워크 경로를 지날 때 적용되는 확장 지점
- 패킷 흐름마다 최대 5 개의 Hook을 순차 통과
- 테이블
네트워크 스택이란?
- User-Space Socket API
- └─ Transport (TCP/UDP, ICMP)
- └─ Network (IP, ARP, ICMPv6) ← netfilter Hook 위치
- └─ Link (Ethernet, 802.11, veth, bridge)
- └─ Physical (Copper, Fiber, Radio)
- 계층별 책임 분리로 설계
- 데이터는 위→아래로 내려가면서 헤더가 추가되고, 수신 측에서는 아래→위로 헤더를 제거
- 컨테이너 격리는 Link 계층(veth)과 Network Namespace에서 이루어지며, NAT·방화벽은 **Network 계층(netfilter)**에서 작동한다.