컨테이너끼리 통신이 안 되거나, localhost로 접속이 안 되거나, 포트 매핑이 안 먹힐 때 십중팔구는 네트워크 모드를 잘못 골랐거나 모드의 동작을 오해한 경우입니다. 도커는 컨테이너를 띄울 때 네트워크 모드를 정하는데, 기본은 bridge이고 host, none이 따로 있습니다. 각 모드가 무엇을 다르게 하는지 알면 대부분의 통신 문제가 바로 풀립니다.
세 가지 모드
| 모드 | 동작 | 포트 매핑 | 격리 |
|---|---|---|---|
bridge (기본) | 도커 내부 가상망에 연결, NAT | -p 필요 | 높음 |
host | 호스트 네트워크를 그대로 공유 | 불필요(직접 노출) | 없음 |
none | 네트워크 인터페이스 없음(loopback만) | 불가 | 완전 격리 |
bridge는 컨테이너마다 사설 IP를 받고 호스트와 NAT로 연결됩니다. 그래서 외부에서 접속하려면 -p 8080:80처럼 포트를 매핑해야 합니다.
직접 확인
로컬 터미널
docker network ls # 네트워크 목록
docker run -d --name web -p 8080:80 nginx # bridge + 포트 매핑
docker inspect web --format '{{.NetworkSettings.IPAddress}}'
host 모드는 매핑 없이 호스트 포트를 바로 씁니다.
Docker
docker run -d --network host nginx # 호스트의 80번을 그대로 점유
상황별 선택
① 여러 컨테이너가 서로 이름으로 통신 — 기본 bridge가 아니라 사용자 정의 네트워크를 만드세요. 기본 bridge는 컨테이너 이름 DNS가 안 되지만, 직접 만든 네트워크는 됩니다.
로컬 터미널
docker network create appnet
docker run -d --name db --network appnet postgres
docker run -d --name api --network appnet myapi # api에서 `db`로 접속 가능
② 호스트 성능이 중요하거나 동적 포트가 많음 — host. NAT 오버헤드가 없지만 포트 충돌과 격리 상실을 감수해야 합니다. (참고: host는 리눅스에서 동작하며 Docker Desktop의 macOS/Windows에서는 제약이 있습니다.)
③ 외부 통신이 전혀 필요 없는 배치 작업 — none. 공격 표면을 최소화합니다.
자주 막히는 지점
- 컨테이너 안에서
localhost는 그 컨테이너 자신입니다. 호스트의 서비스에 붙으려면host.docker.internal(또는 host 모드)을 씁니다. - 컨테이너 이름으로 접속하려는데
could not resolve host가 나오면, 기본 bridge에 있다는 뜻 — 사용자 정의 네트워크로 옮기세요.
체크리스트
로컬 터미널
docker inspect <컨테이너> --format '{{json .NetworkSettings.Networks}}'
docker network inspect <네트워크> # 어떤 컨테이너가 붙었는지
docker port <컨테이너> # 매핑된 포트 확인
bridge·host·none을 직접 띄워 보며 통신 차이를 확인하고 사용자 정의 네트워크로 컨테이너를 이름으로 연결하는 실습은 도커 트랙에서 회원가입 없이 무료로 할 수 있습니다.