Gi-Log

Docker 네트워크 기초 본문

Docker/네트워크

Docker 네트워크 기초

돌잔 2023. 6. 12. 11:42

docker를 사용할 때 --port 옵션을 활용한 docker host와 container간 포트 맵핑 외에는 신경을 쓰지 않고 있었는데, 조금이라도 더 명확하게 파악하고 싶어졌다.

* 기본적인 docker 네트워크 형태
* docker 설치시 구성되는 네트워크
* bridge는 어떻게 구성되는 것일까?
  * docker 0
  * 그래서 docker0와 bridge의 관계는?
* 그래서 bridge/docker0를 이용한 통신은 어떻게 이루어지는데?
* 정리하자면..
* 새롭게 궁금한 내용들

기본적인 docker 네트워크 형태

직접 손으로 그려서... 몹시 조잡하지만 대략 docker 네트워크 구조를 그리면 (일반적으로) 위와 같다.

주목할 점은 컨테이너(들)과 도커 호스트 간에 bridge라는 네트워크 구조가 이용된다는 것이다.


docker 설치시 구성되는 네트워크

docker bridge에 대해서 설명하기 전에, docker를 설치할때 함께 구성되는 docker network들을 살펴보면 다음과 같다.

docker network ls

host, none 그리고 bridge가 설치되는 것을 확인할 수 있다. 즉 bridge라는 docker network가 기본적으로 구성되는 것인데,

bridge라고 하니.. OSI Layer2의 브릿지도 떠오르고, 스위치도 떠오르고 혼란이 있을 수 있다.

그 형태나 구조 등이 전혀 연관이 없다고 할 수는 없지만, 여기서는 그런 것들은 떠올리지 말고 그냥 "default docker network의 이름"정도로 해석하면 이해가 편할 것 같다.


bridge는 어떻게 구성되는 것일까?

중간 정리를 하자면, 일반적으로 컨테이너(들)는 docker host와 통신을 위해서 bridge라는 docker network를 이용한다.

그럼 bridge는 대체 뭘까? 얘가 어떻게 생겨먹었길래 docker host와 통신이 가능한 걸까?

docker0

docker를 설치하면 기본적으로 구성되는 docker network가 bridge라고 했는데, docker를 설치하면 기본적으로 구성되는 것이 한가지 더 있다!

docker host에 추가되는 가상의 network interface인데, 이를 docker0 라고 한다....

docker host에서 ifconfig 명령어를 입력해서 확인할 수 있다.(현재 내 docker host의 os는 centos:7.8 이며 os나 설치된 패키지에 따라서 명령어는 달라질 수 있다. e.g. ip addr)

ifconfig

위와 같이 docker host의 eth0외에 docker0라는 인터페이스가 확인되는데, ip는 172.17.0.1/16 이다.

그래서 docker0와 bridge의 관계는?

docker0: docker 설치시 기본으로 구성되는 virtual network interface

bridge: docker 설치시 기본으로 구성되는 docker network

그래서 위 둘의 관계는 뭘까?

docker network inspect bridge

docker network inspect bridge 결과

위 명령어를 통해서 bridge에 대한 정보를 파악할 수 있는데, com.docker.netowrk.bridge.name을 통해서 docker network인 bridge가 network interface인 docker0를 이용하는 것을 알 수 있다.

따라서 bridge에 연결된 모든 컨테이너들의 Gateway는 docker0의 ip인 172.17.0.1이 된다.

그래서 bridge/docker0를 이용한 통신은 어떻게 이루어지는데?

눈으로 보는 것이 가장 빠를 것 같다.

bridge 네트워크를 이용하고 docker host의 19611번 포트와 맵핑된 3000번 포트를 갖는 컨테이너를 실행해보자.

docker run -it -d -p 19611:3000 --name centos-with-port centos:7

이 컨테이너는, (내 테스트 환경 기준으로) 172.17.0.2 ip를 갖는다.

이어서 docker host에서 iptables를 확인해보면...

iptables -t nat -L

# 결과
...
Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere
DNAT       tcp  --  anywhere             anywhere             tcp dpt:19611 to:172.17.0.2:3000

docker host의 19611 포트로 전달된 요청은, 172.17.0.2 ip를 갖는 컨테이너의 3000번 포트로 포워딩(전달)하도록 규칙이 설정되어 있는 것을 알 수 있다.

이는 docker run/start 등의 명령어로 컨테이너를 실행시켰을 때, 자동으로 iptables에 추가되는 설정이다.


정리하자면...

  • docker를 설치하면, docker0라는 virtual network interface가 docker host에 추가된다.
  • 그리고 가장 기본적인 docker network인 bridge가 생성/설정되며 이 docker network는, 인터페이스 docker0를 이용하여 컨테이너 <-> docker host 또는 컨테이너 <-> 컨테이너의 통신을 가능토록 한다.
  • 이런 통신이 가능한 것은, 해당 bridge 네트워크를 이용하는 컨테이너가 생성/실행될 때 docker host의 iptables에 직접 포트 포워딩 규칙(NAT)이 추가되기 때문이다.
    • docker run할때 --network 옵션을 명시하지 않으면, default docker network인 bridge를 암묵적으로 이용하게 되어 있다.

새롭게 궁금한 내용들

정리하면서 몇가지 궁금해진 사항들이 있다.

  • 만약 docker run할 때 host와 컨테이너간 포트 맵핑을 하지 않는다면, iptables에 NAT 설정이 추가가 될 것인가?
  • host와 포트 맵핑을 하지 않아도, 동일한 docker network에 묶여있는 컨테이너들 간에 통신이 가능할것인가?(아마도 가능할 것이다.)
  • 가장 처음에 그려둔 그림에, bridge에 묶여있는 veth과 컨테이너의 eth0은 어떤 관계이지? 어떻게 맵핑되어 있는 것이지?

위 내용과 관련된 실험, 정리 등은 다음 포스트에 정리해보도록 하겠다.

Comments