[Infra] Docker 컨테이너는 어떻게 통신할까?

2026. 6. 4. 22:54·Infra

들어가기

https://geniusjun4663.tistory.com/120

 

[Infra] Container 딥다이브 - Linux Kernel에서 시작하는 Docker 자세히 알아보기

들어가며솔직하게 지금까지는 Docker를 활용하기에 바빴다. Dockerfile로 image 관리해보고,, port 격리해보고,,, 아래의 명령어를 필요할때 써보기에 급급했다.docker rundocker psdocker logsdocker exec... 하지만

geniusjun4663.tistory.com

 

이전 글에서는 컨테이너 개념이 Linux Kernel 명령어 3가지의 조합(namespace, cgroups, Union FileSystem)이란 것을 자세하게 알아보았고, Docker는 그 조합을 개발자가 원할하게 쓸 수 있도록 제공하는 것임을 정리했다.

 

평소에는 Docker 컨테이너로 격리를 시킨다음 서로 필요한 port끼리 포워딩해서 원하는 flow를 구축한다. (blue/green 배포, 서비스 흐름 등등..) 이런 구현 관점에서는 컨테이너 격리가 매우 유용하지만, 어떻게 그들은 통신하는 것일까???

 

여태까지 필자도 안정성 있는 무중단 oo배포, 의존성을 격리시키기 위한 docker 컨테이너 활용 등등 목적을 달성하기 위한 구현에만 급급했다.

이 글에서는 격리된 컨테이너들끼리 어떻게 통신하는지 조금 더 자세하게 정리해볼까 한다.


본문으로

1. 이더넷(Ethernet) - 서버의 인터페이스를 이해하자

먼저 컨테이너들끼리의 통신을 이해하기 전에, 서버 자체가 외부와 어떻게 통신하는지 알아야한다. 이더넷(Ethernet)이라고 들어봤는가?!

네트워크 전공시간에 잠깐(?) 나오는 개념이다.

가정이나 사무실에서 컴퓨터, 스마트 TV, 게임기 등을 케이블로 연결해 근거리 통신망(LAN)을 구축할 때 사용하는 가장 표준적인 유선 네트워크 통신 기술

이더넷에 대해 다루면 다른 내용이 너무 많아지니, 이더넷은 서버가 외부 네트워크와 통신하기 위한 통로 정도로 이해하고 설명을 이어가겠다. 이 이더넷을 관례적으로 eth0이라고 부르고 Linux에서는 eth0을 네트워크 인터페이스로 제공한다.

실제 Ubuntu나 EC2 환경에서는 네트워크 인터페이스를 구현하여 제공한다. ens3, ens5, enp0s3 같은 이름으로 보이기도 한다. 

 

즉 서버의 외부 네트워크 통신을 위해, 이더넷이 서버쪽에 붙어있는 있는 것이다. (약간 인터넷 게이트 웨이랄까..)


2. 그렇다면 정말 EC2에도 이더넷이 붙어있을까?

EC2도 같은 VPC 리소스끼리는 내부 통신이 가능하다! 그럼 이더넷이 붙어있어야 하지 않겠는가??

그래서 EC2에 들어가서 "ip addr show"(너의 ip를 보여줘!!) 를 치면 놀랍게도 ip가 2개가 나온다(lo, ens5) 

어? ens5??? -> 아까 Linux에서 네트워크 인터페이스(eth0)를 제공하고 ubuntu나 EC2환경에서는 ens3, ens5 같은 이름으로 보인다고 하지 않았나?

그렇다. lo는 자기자신을 뜻하는 ip(127.0.0.1 -> localhost)이고 ens5는 EC2에 붙어있는 네트워크 인터페이스의 ip(192.168.0.31 -> VPC 내부통신에 쓰임)이다

 

예전에는 EC2의 lo에 해당하는 ip만 신경썻었는데,,, 이런 친구가 숨어있다니🤩

즉, Docker를 설치하기 전에도 서버는 이미 자신만의 네트워크 인터페이스를 가지고 있고, 이 인터페이스를 통해 외부와 통신하고 있었다.


3. Docker를 설치하면 이더넷은 어떻게 될까?

냅다 도커를 설치해서 다시 IP를 검색해보자😇 

docke를 깔고 다시 ip를 검색한 결과

네트워크 ip 구조에 docker0라는 인터페이스가 새로 추가되었다!!

 

docker0는 Docker가 기본적으로 만드는 Bridge 네트워크 인터페이스다. 쉽게 말하면 호스트 서버와 컨테이너들 사이에 놓이는 가상의 네트워크 스위치 같은 역할을 한다.

Docker 컨테이너는 기본적으로 호스트의 네트워크 인터페이스를 그대로 사용하는 것이 아니라, Docker가 만든 가상 네트워크 안에서 동작한다. 그래서 컨테이너들은 보통 172.17.0.x 같은 사설 IP를 할당받는다.


4. 컨테이너에도 eth0가 있다

컨테이너에도 이더넷이 있어야 외부 네트워크와 통신하지 않겠는가! 그렇게 되면 호스트에도 네트워크 인터페이스가 있고, 컨테이너 안에도 eth0가 있다. 좀 더 자세한 설명을 위해 아래 그림을 보자!

위의 그림에 근거하여, EC2 안의 Docker 컨테이너에서 발생한 트래픽이 인터넷 게이트웨이까지 나가는 흐름을 차근차근 정리해보자. 눈 부릅뜨고 읽어보자!!

 

1. 컨테이너는 독립된 네트워크 네임스페이스를 가진다. 독립적인 컨테이너 내부에는 외부 통신을 위한 eth0 인터페이스가 존재한다.

 

2. 이 컨테이너 내부의 eth0는 호스트 쪽의 veth와 연결된다. veth는 virtual ethernet의 줄임말로, 컨테이너와 호스트 네트워크를 이어주는 가상의 이더넷 쌍이라고 볼 수 있다. 

 

3. 여러 컨테이너에서 나온 트래픽은 각각의 veth를 통해 docker0 bridge 인터페이스로 모인다. (이래서 bridge 구나..)

 

4. 이후 컨테이너의 사설 IP 대역, 예를 들어 172.17.x.x은 Linux의 iptables NAT(Network Address Translation) 규칙을 통해 EC2의 private IP로 변환된다.

 

5. 변환된 트래픽은 EC2의 실제 네트워크 인터페이스(eth0)를 통해 VPC 네트워크로 나간다.

 

6. VPC의 라우팅 테이블에 따라 해당 트래픽은 Internet Gateway를 거쳐 외부 인터넷으로 전달된다.

 

전체적인 Flow를 Top-Down으로 정리한 그림은 아래와 같다.


5. Docker의 네트워크 모드가 있다고?!

결론 먼저 말하자면 Docker의 네트워크 모드에는 bridge, host, none 이렇게 3가지가 존재한다.

 

- Bridge

보편적으로 사용하는 mode이다. 여태까지도 bridge 모드를 가정해서 설명했다.

Bridge 모드에서는 컨테이너마다 독립적인 IP가 할당되고, 컨테이너들은 Docker가 만든 브리지 네트워크(docker0) 안에서 통신한다. 

장점은 다음과 같다.

- 컨테이너별 네트워크 격리가 가능하다.
- 기본값이라 사용이 쉽다.
- 대부분의 웹 애플리케이션 운영에 충분하다.
- Docker Compose 환경에서도 자연스럽게 사용된다.

bridge 모드는 내부 IP를 외부로 내보낼 때 NAT 처리를 거쳐야만 한다. 내부의 독립적인 ip를 바꿔줘야 하지 않겠는가!

컨테이너 내부의 172.x.x.x 대역 IP가 호스트의 192.x.x.x 또는 EC2 사설 IP 대역으로 변환되어 외부로 나간다.

 

이 과정에서 약간의 오버헤드는 발생할 수 있다. 하지만 일반적인 웹 서버나 API 서버에서는 bridge 모드의 성능이 충분히 괜찮기 때문에, 특별한 이유가 없다면 bridge 모드를 사용하는 것이 기본적으로 권장된다.

- Host

Host 모드는 컨테이너가 독립적인 네트워크 네임스페이스를 가지지 않고, 호스트의 네트워크를 그대로 공유하는 방식이다.

컨테이너 프로세스 → 호스트 네트워크 직접 사용

그래서 NAT 변환 과정이 줄어들고, 네트워크 성능 면에서 유리할 수 있다. (고성능)

하지만 단점도 명확하다.

- 컨테이너 간 네트워크 격리가 약해진다.
- 포트 충돌이 발생할 수 있다. -> 컨테이너가 host의 port를 그대로 이용하므로!
- 보안적으로 더 신중해야 한다.
- 어떤 컨테이너가 어떤 포트를 쓰는지 관리가 어려워질 수 있다.

따라서 host 모드는 “성능이 좋아 보이니까 무조건 써야지”가 아니라, 정말로 네트워크 성능이 중요하고 격리보다 성능이 우선인 경우에 선택하는 방식이다.

모니터링을 생각해보자. 모니터링 에이전트는 호스트의 네트워크 상태를 직접 관찰해야 하고, 입출력이 많을 수 있기 때문에 host 모드로 띄우기 딱 좋다.

- None

None 모드는 말 그대로 컨테이너에 네트워크를 붙이지 않는 방식이다. 외부 통신도 안 되고, 다른 컨테이너와의 통신도 기본적으로 불가능하다.

일반적인 웹 애플리케이션에서는 거의 사용하지 않는다. 다만 네트워크가 필요 없는 배치 작업이나, 보안상 네트워크를 완전히 차단해야 하는 특수한 경우에 사용할 수 있다.


6. 컨테이너끼리는 이름으로 통신할 수 있다. (DNS 흉내내는 파일 -> "resolv.conf")

컨테이너를 운영하다 보면 컨테이너의 IP에 직접 접근하는 방식은 좋지 않다. 컨테이너는 언제든 삭제되고 다시 생성될 수 있으며, 이 과정에서 IP가 바뀔 수 있기 때문이다.

Docker에서는 bridge network를 만들어 컨테이너끼리 이름으로 통신할 수 있게 해준다.

 

예를 들어 다음처럼 appnet이라는 네트워크를 만들고, db 컨테이너와 web 컨테이너를 같은 네트워크에 붙였다고 가정해보자.

docker network create appnet

docker run -d --name db --network appnet postgres
docker run -d --name web --network appnet myapp

이제 web 컨테이너 안에서는 db 컨테이너의 IP를 몰라도 된다. 다음처럼 컨테이너이름인 db로 접근할 수 있다.

curl http://db:5432

같은 network 안에서는 컨테이너 이름이 곧 호스트명처럼 동작한다. -> 마치 우리가 naver.com으로 홈페이지를 들어갔을 때 DNS가 도메인에 해당하는 ip를 찾아서 반환해주는 것처럼 말이다!!

 

그렇다! Docker 컨테이너 내부에 DNS서버의 역할을 흉내내는 파일이 있다!

컨테이너 내부에서 /etc/resolv.conf 파일을 확인해보면 다음과 같이 Docker의 DNS 서버가 등록되어 있는 것을 볼 수 있다.

cat /etc/resolv.conf
...
nameserver 127.0.0.11 -> 이게 내장 DNS 주소임!!

여기서 127.0.0.11은 Docker가 컨테이너 내부에 제공하는 embedded DNS이다.

컨테이너가 db라는 이름으로 요청을 보내면, Docker의 내장 DNS가 이름이 db라는 컨테이너에 어떤 IP주소가 붙어있는지 확인하고 그것을 반환해준다.

 

덕분에 컨테이너가 재시작되어 IP가 바뀌더라도, 컨테이너 이름은 그대로 유지되기 때문에 안정적으로 통신할 수 있다.

 

이 개념은 Docker Compose를 사용할 때도 그대로 이어진다. 예를 들어 app 서비스와 db 서비스가 같은 Compose 네트워크에 있다면, 애플리케이션에서는 DB 주소를 localhost가 아니라 서비스 이름인 db로 설정한다. (너무 당연하게 생각했던 포인트여서 적어본다.)

jdbc:mysql://db:3306/mydb

즉, Docker에서 컨테이너 간 통신의 핵심은 같은 네트워크에 묶고, IP가 아니라 이름으로 접근하는 것이다.


마무리하며

격리된 환경을 위해 썼던 도커 -> 격리 잘 되었습니다~ -> 그래서 개네가 어떻게 통신하는데? 로 시작되어 정리된 글이었다...

 

Docker 컨테이너는 독립된 환경처럼 보이지만, 실제로는 호스트의 네트워크 인터페이스, Linux namespace, veth, docker0, iptables NAT 같은 여러 리눅스 기능 위에서 동작한다.

 

이제 Docker를 잘 안다는 것은 단순히 컨테이너를 띄우는 명령어를 아는 것이 아니라, 컨테이너가 호스트 위에서 어떤 방식으로 네트워킹 되는지를 이해하는 것이라고 생각한다!!

'Infra' 카테고리의 다른 글

[Infra] Container 딥다이브 - Linux Kernel에서 시작하는 Docker 자세히 알아보기  (0) 2026.05.28
[Infra] 모니터링 서버 도입 전에 할 수 있는 부하 테스트와 성능 병목 확인(Amazon CodeGuru Profiler + k6 스트레스 테스트)  (0) 2026.05.24
[Infra] Prometheus와 Grafana로 우리 서비스의 개선점과 에러 찾기  (0) 2026.05.23
[Infra] 인스턴스 연결성 검사 실패 문제. 메모리가 부족하면 ssh 연결도 막힌다.  (0) 2026.02.21
[Infra] Blue/Green 무중단 배포 (Docker, Nginx, GitHub Actions) 구현해보기  (5) 2025.11.21
'Infra' 카테고리의 다른 글
  • [Infra] Container 딥다이브 - Linux Kernel에서 시작하는 Docker 자세히 알아보기
  • [Infra] 모니터링 서버 도입 전에 할 수 있는 부하 테스트와 성능 병목 확인(Amazon CodeGuru Profiler + k6 스트레스 테스트)
  • [Infra] Prometheus와 Grafana로 우리 서비스의 개선점과 에러 찾기
  • [Infra] 인스턴스 연결성 검사 실패 문제. 메모리가 부족하면 ssh 연결도 막힌다.
노을을
노을을
진인사대천명
  • 노을을
    노을의 개발일기장
    노을을
  • 전체
    오늘
    어제
    • All (108)
      • Java & Kotlin (16)
      • Problem Solve (46)
      • Spring (4)
      • Infra (6)
      • DB (2)
      • Project (2)
        • SOMA (1)
        • OJik (1)
      • OpenSource (3)
      • Various Dev (23)
        • 우아한테크코스 (9)
        • Git&Github (2)
        • Unity (12)
      • Book (3)
      • Writing (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    8기
    코테
    비트마스킹
    코딩
    백준
    합격
    프리코스
    게임개발
    개발자
    트러블슈팅
    우아한테크코스
    자바
    개발
    알고리즘
    유니티
    contribute
    오픈소스
    시뮬레이션
    도커
    java
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
노을을
[Infra] Docker 컨테이너는 어떻게 통신할까?
상단으로

티스토리툴바