Docker 네트워크 기초 — bridge, host, none의 동작 원리
두 개의 컨테이너를 띄웠는데 서로 통신이 안 됩니다. 같은 머신에서 돌고 있는데 왜 연결이 안 되는 걸까요?
Docker 네트워크의 기본 개념
Docker는 각 컨테이너에 독립적인 네트워크 환경을 제공합니다. 리눅스의 네트워크 네임스페이스를 활용하여 컨테이너마다 별도의 IP, 라우팅 테이블, 포트 공간을 가집니다.
# 현재 존재하는 네트워크 확인
docker network ls
# NETWORK ID NAME DRIVER SCOPE
# a1b2c3d4e5f6 bridge bridge local
# g7h8i9j0k1l2 host host local
# m3n4o5p6q7r8 none null local
Docker를 설치하면 위 세 개의 네트워크가 기본으로 생성됩니다.
bridge — 기본 네트워크 드라이버
컨테이너를 생성할 때 네트워크를 지정하지 않으면 기본 bridge 네트워크에 연결됩니다.
동작 원리
호스트 머신
┌─────────────────────────────────────┐
│ docker0 (172.17.0.1) │
│ │ │
│ ┌────────┼────────┐ │
│ │ │ │ │
│ ┌──┴──┐ ┌──┴──┐ ┌──┴──┐ │
│ │veth1│ │veth2│ │veth3│ │
│ └──┬──┘ └──┬──┘ └──┬──┘ │
│ │ │ │ │
│ ┌──┴──┐ ┌──┴──┐ ┌──┴──┐ │
│ │ C1 │ │ C2 │ │ C3 │ │
│ │.0.2 │ │.0.3 │ │.0.4 │ │
│ └─────┘ └─────┘ └─────┘ │
└─────────────────────────────────────┘
- Docker는 호스트에
docker0이라는 가상 브릿지를 생성합니다. - 각 컨테이너는
veth pair(가상 이더넷 쌍)로docker0에 연결됩니다. - 컨테이너는
172.17.0.x대역의 IP를 자동으로 할당받습니다.
# 컨테이너 실행 (기본 bridge에 연결)
docker run -d --name web nginx
# IP 주소 확인
docker inspect web --format '{{.NetworkSettings.IPAddress}}'
# 172.17.0.2
# 호스트에서 브릿지 확인
ip link show docker0
brctl show docker0
기본 bridge의 한계
# 컨테이너 두 개 실행
docker run -d --name web nginx
docker run -d --name app node:20-alpine sleep 3600
# app에서 web으로 이름으로 접근 → 실패!
docker exec app ping web
# ping: bad address 'web'
# IP로는 가능
docker exec app ping 172.17.0.2
# PING 172.17.0.2: 64 bytes ...
기본 bridge 네트워크에서는 컨테이너 이름으로 DNS 해석이 되지 않습니다. IP 주소를 직접 사용해야 하는데, IP는 컨테이너를 재시작할 때마다 바뀔 수 있어서 실용적이지 않습니다.
사용자 정의 bridge 네트워크
실무에서는 거의 항상 사용자 정의 bridge 네트워크를 사용합니다.
# 사용자 정의 네트워크 생성
docker network create my-network
# 네트워크를 지정하여 컨테이너 실행
docker run -d --name web --network my-network nginx
docker run -d --name app --network my-network node:20-alpine sleep 3600
# 이름으로 접근 → 성공!
docker exec app ping web
# PING web (172.18.0.2): 56 data bytes
# 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.089 ms
기본 bridge vs 사용자 정의 bridge
| 기능 | 기본 bridge | 사용자 정의 bridge |
|---|---|---|
| 자동 DNS 해석 | X | O |
| 네트워크 격리 | 모든 컨테이너가 같은 네트워크 | 네트워크별 격리 |
| 동적 연결/해제 | X | O |
| 서브넷/게이트웨이 설정 | X | O |
--link 필요 | 컨테이너 연결 시 필요 | 불필요 |
네트워크 옵션 지정
# 서브넷과 게이트웨이 직접 설정
docker network create \
--subnet 10.0.0.0/24 \
--gateway 10.0.0.1 \
my-custom-network
# 컨테이너에 고정 IP 할당
docker run -d --name db \
--network my-custom-network \
--ip 10.0.0.100 \
postgres:16-alpine
다중 네트워크 연결
하나의 컨테이너를 여러 네트워크에 동시에 연결할 수 있습니다.
docker network create frontend
docker network create backend
# 웹 서버는 프론트엔드와 백엔드 모두 연결
docker run -d --name web --network frontend nginx
# 실행 중인 컨테이너에 네트워크 추가
docker network connect backend web
# DB는 백엔드에만 연결 (프론트엔드에서 직접 접근 불가)
docker run -d --name db --network backend postgres:16-alpine
┌── frontend ──┐ ┌── backend ──┐
│ │ │ │
│ browser ───┼── web ──┼── db │
│ │ │ │
└──────────────┘ └─────────────┘
이 패턴으로 네트워크 계층을 분리하여 보안을 강화할 수 있습니다.
host — 네트워크 격리 없음
host 모드는 컨테이너가 호스트의 네트워크 스택을 직접 사용합니다.
# host 네트워크로 실행
docker run -d --network host nginx
# 호스트의 80 포트에서 직접 서비스됨
# -p 포트 매핑이 필요 없음
curl http://localhost:80
특징
- 네트워크 네임스페이스 격리가 없습니다.
- 포트 매핑(
-p)이 필요 없고 무시됩니다. - 네트워크 성능이 가장 좋습니다 (NAT 오버헤드 없음).
- 포트 충돌 위험이 있습니다 (호스트에서 이미 사용 중인 포트는 사용 불가).
- Linux에서만 완전히 지원됩니다 (macOS/Windows에서는 VM 안에서 동작).
사용 사례
- 네트워크 모니터링 도구 (호스트 네트워크 트래픽 직접 관찰)
- 성능이 매우 중요한 경우
- 많은 수의 포트를 사용하는 애플리케이션
# 성능 테스트를 위한 host 모드
docker run --network host \
--name benchmark \
fortio/fortio load -qps 0 http://target:8080
none — 네트워크 비활성화
none 모드는 컨테이너에 loopback 인터페이스(lo)만 제공합니다. 외부 네트워크 접근이 완전히 차단됩니다.
docker run --network none alpine ip addr
# 1: lo: <LOOPBACK,UP,LOWER_UP>
# inet 127.0.0.1/8 scope host lo
# → 네트워크 인터페이스가 lo만 존재
사용 사례
- 네트워크가 필요 없는 배치 처리 (데이터 변환, 파일 처리)
- 보안이 중요한 암호 연산
- 네트워크 격리가 필요한 테스트
# 네트워크 없이 파일 처리
docker run --network none \
-v $(pwd)/data:/data \
myprocessor:latest
DNS 자동 해석
사용자 정의 네트워크에서 Docker는 내장 DNS 서버(127.0.0.11)를 제공합니다.
# DNS 설정 확인
docker run --network my-network alpine cat /etc/resolv.conf
# nameserver 127.0.0.11
# options ndots:0
# 컨테이너 이름으로 해석
docker exec app nslookup web
# Server: 127.0.0.11
# Address: 127.0.0.11:53
# Name: web
# Address: 172.18.0.2
네트워크 별칭(alias)
# 별칭 지정
docker run -d --name postgres-primary \
--network my-network \
--network-alias db \
--network-alias database \
postgres:16-alpine
# db 또는 database로 접근 가능
docker exec app ping db
docker exec app ping database
여러 컨테이너에 같은 별칭을 주면 라운드 로빈 방식으로 DNS가 해석됩니다(간단한 로드 밸런싱).
네트워크 명령어 정리
# 네트워크 생성
docker network create my-network
# 네트워크 목록
docker network ls
# 네트워크 상세 정보 (연결된 컨테이너, 서브넷 등)
docker network inspect my-network
# 실행 중인 컨테이너를 네트워크에 연결
docker network connect my-network existing-container
# 네트워크에서 분리
docker network disconnect my-network existing-container
# 사용하지 않는 네트워크 정리
docker network prune
# 네트워크 삭제
docker network rm my-network
정리
- Docker는
bridge,host,none세 가지 기본 네트워크 드라이버를 제공합니다. - 사용자 정의 bridge 네트워크를 사용해야 컨테이너 이름으로 DNS 해석이 가능합니다. 기본 bridge는 실무에서 권장하지 않습니다.
host모드는 네트워크 성능이 중요할 때,none은 네트워크 격리가 필요할 때 사용합니다.- 다중 네트워크를 활용하면 프론트엔드/백엔드 네트워크를 분리하여 보안을 강화할 수 있습니다.
- Docker의 내장 DNS 서버가 사용자 정의 네트워크에서 서비스 디스커버리 역할을 합니다.
댓글 로딩 중...