[서버] Docker Network 에 대해

최동근·2023년 8월 27일
2

docker

목록 보기
4/4
post-thumbnail
post-custom-banner

안녕하세요 도커 공부에 심취해 있는 요즘, 도커 공부를 하다보니 도커 컨테이너의 Network 에 대해 알고 싶어졌습니다.
도커에 관련된 다양한 기술들을 배우다 보니 이 부분에 대해서 정리하고 넘어가는게 좋을 것 같습니다.
따라서 이번 포스팅에서는 Docker Network 에 대해 정리해보려고 합니다 ❗️

🐳 도커 네트워크란?

도커 네트워크(Docker Network) 란 Docker 컨테이너 간의 통신을 관리하고 격리하기 위한 기능을 제공하는 것입니다.
컨테이너화된 애플리케이션은 여러개의 컨테이너로 구성될 수 있는데, 이들 컨테이너가 서로 통신하고 데이터를 주고 받아야 할 경우가 있습니다.
도커 네트워크를 통해 이러한 컨테이너간 통신을 쉽게 설정하고 관리할 수 있도록 도와줍니다.
정리하자면, 같은 호스트 내에서 실행중인 컨테이너 간 연결할 수 있도록 돕는 논리적 네트워크 개념이다.

 version: '3'

services:
  front: # front container
    image: frontend
    networks:
      - mynetwork
  backend: # backend container
    image: backend
    networks:
      - mynetwork
  db: # db container
    image: mysql
    networks:
      - mynetwork
    environment:
      MYSQL_ROOT_PASSWORD: mypassword

networks:
  mynetwork:
	   .... # mynetwork 네트워크

위의 yml 은 Docker Compose 로 구성한 다중 컨테이너입니다.
fronted,backend,db 컨테이는 모두 networks 라는 항목을 통해 mynetwork 라는 네트워크로 묶여 있습니다.
이렇게 여러 컨테이너로 구성된 애플리케이션은 같은 네트워크 내에서 통신하여 데이터를 주고받을 수 있습니다😊

🐳 도커 네트워크 구조에 대해

호스트에서 컨테이너가 생성되는 경우 결국 해당 컨테이너도 어플리케이션이기 때문에 IP 및 포트 등 네트워크을 구성하며, 이에 대한 정보가 할당되어야 합니다.
그렇다면 호스트에 의해 구동되는 컨테이너는 어떻게 네트워크를 구성할까요?

기본적으로 도커를 호스트 OS 에 설치하면 여러가지 네트워크 드라이버(Network Driver) 들이 설치되며, 구동되는 컨테이너에 IP 주소를 순차적으로 할당하고 해당 컨테이너는 네트워크를 구성할 때 원하는 네트워크 드라이버를 선택할 수 있습니다.
어떤 명령어을 통해 컨테이너 구동시 네트워크를 구성하는지는 마지막에 알아봅시다 ❗️

[네트워크 인터페이스 계층]


도커 네트워크의 구조를 본격적으로 알아보기 전 네트워크 인터페이스 라는 것을 먼저 정리하고 가겠습니다.
해당 이미지는 일반적인 네트워크 인터페이스 계층 을 설명하는 이미지입니다.

네트워크 인터페이스(Network Interface)컴퓨터나 장치가 네트워크와 상호작용하기 위한 연결점이며, 데이터를 주고받을 수 있는 하드웨어 또는 소프트웨어 구성 요소입니다. 네트워크 인터페이스 는 컴퓨터와 네트워크 간의 통신을 가능하게 하며, 데이터 전송과 수신을 처리합니다.

네트워크 계층을 통해 컴퓨터와 외부 네트워크의 물리적인 연결이 이루어지며, [1] 컴퓨터로부터 나오는 디지털 데이터을 전기 신호나 전파같은 물리적 신호로 변환하여 네트워크로 변환시키며 동시에 [2] 네트워크로부터 받은 물리적 신호를 컴퓨터에서 처리할 수 있는 디지털 데이터로 변환합니다 🛜

TCP/IP 모델 최하층에 위치한 네트워크 인터페이스 계층은 이름에서 알 수 있듯이 인접한 네트워크 기기 간에, 즉 전송 매체로 연결되어 전기신호나 전파같은 물리적 신호가 도달하는 범위에서 데이터를 전송하는 역할을 합니다.
네트워크 인터페이스 계층이 직접 연결된 네트워크용 하드웨어 기기 간에 데이터 전송을 제어함으로써 상위 계층은 하드웨어의 종류에 상관없이 통신할 수 있게 됩니다 🔥

[veth 에 대해]

도커 네트워크 구조를 알아보기 전 마지막으로 veth 에 대해 알아봅시다.

리눅스의 Virtual Ethernet Interface 을 의미합니다.
앞서 네트워크 인터페이스 에 관해서 살펴보았던 것처럼 실제 컴퓨터의 랜카드(NIC) 을 통해 랜포트 을 열어서 랜 케이블 에 연결하는 것이 아니라, 가상의 네트워크 인터페이스를 생성하는 것입니다.

생각을 해보면 컨테이너로 구동된 애플리케이션은 일반적인 컴퓨터 애플리케이션 처럼 물리적인 네트워크 인터페이스를 사용할 수 없습니다 ⛔️

veth 는 일반적인 네트워크 인터페이스와는 달리 패킷을 전달받으면, 자신에게 연결된 다른 네트워크 인터페이스로 패킷을 보내주는 식으로 동작하기 때문에 항상 쌍으로 생성해줘야 합니다.
한 쪽에서 다른 쪽으로 패킷을 전송할 수 있으며, 한 쪽에 다운된 경우 나머지 한 쪽도 정상적으로 기능하지 않는 것이 특징입니다.
도커에서는 실행중인 컨테이너 수 만큼 veth 로 시작하는 인터페이스가 생성됩니다.

[도커 네트워크 구조]

본격적으로 도커 네트워크의 구조에 대해 알아보겠습니다.
앞서 언급했던 것처럼 도커 컨테이너도 결국 네트워크를 구성합니다. 따라서 컨테이너마다의 IP 와 포트가 존재하겠죠?
도커는 호스트로부터 실행되는 컨테이너에 172.17.0.x 의 IP 을 순차적 으로 할당합니다.

이를 확인해보기 위해 아래의 명령어를 통해 간단한 ubuntu container 을 실행시켜보겠습니다.

docker run -it ubuntu:latest

이후 ubuntu OS 에서 apt-get update 을 통해 ubuntu OS에서 사용 가능한 패키지들과 그 버전에 맞는 정보를 업데이트 합니다.
그 후, apt-get install net-tools 을 통해 네트워크 관련 도구를 설치해줍니다.
해당 과정을 꼭 진행시켜야 ubuntu OS 에서 네트워크와 관련된 기능을 사용할 수 있습니다 ❗️

모든 준비를 마치고 도커 컨테이너로 구동되는 ubuntu OS 에 ifconfig 명령어를 실행시켜보겠습니다 👨‍💻
참고 - ifconfig 명령어란?

ifconfig 명령어를 통해 컨테이너의 네트워크 인터페이스에 대한 정보를 확인할 수 있습니다.

위의 스크린샷을 보면 IO 네트워크 인터페이스와 eth0 네트워크 인터페이스가 각 172.17.0.1 과 172.17.0.2 가 할당된 것을 확인할 수 있습니다.
여기서 Io 네트워크 인터페이스는 루프백(자기 자신한테 보내는) 과 관련된 것이고 eth0 은 외부 네트워크와 관련된 것입니다 ❗️
해당 도커 컨테이너에 아무런 설정을 하지 않는다면 외부에서 접근할 수 없으며 오로지 해당 도커 컨테이너를 구동시킨 호스트에서만 접근 가능합니다.

그렇다면 외부에서 해당 컨테이너에 접근할 수 있는 방법은 없는걸까요? 🤔
여기서 앞에서 살펴본 veth 가 사용됩니다 ❗️

외부 네트워크에 컨테이너 어플리케이션을 노출하기 위해서는 eth0 의 IP/PORT 을 호스트의 IP/PORT 에 바인딩시켜야합니다.

외부와의 네트워크 연결은 컨테이너마다 eth0에 대응되는 veth라는 가상 네트워크 인터페이스를 호스트에 생성함으로써 이루어집니다. 그리고 각각의 IP 주소와 포트를 입력해 컨테이너를 외부에 노출 시킬 수 있습니다. veth는 도커 호스트에서 ifconfig 명령어를 입력하면 확인 가능합니다.

즉, eth0에 대응되는 vethXXXX이라는 이름의 veth interface와 브릿지 네트워크에 컨테이너의 interface가 바인딩되는 형태로 통신합니다.

veth 인터페이스는 사용자가 직접 생성할 필요는 없고 컨테이너가 생성될 때 도커 엔진이 자동으로 생성합니다. 도커 컨테이너가 실행될 때 네트워크 드라이버를 따로 지정하지 않으면 docker0라고 하는 브릿지 네트워크를 default로 사용합니다. 이 브릿지 네트워크의 역할은 veth와 호스트의 eth0의 다리 역할을 합니다. 🦵

[도커 네트워크 구조 정리]

  • 도커는 컨테이너에 내부 IP 을 순차적으로 할당
  • 내부 IP(호스트 내부) 는 컨테이너를 재시작할 때마다 변경될 수 있음
  • 내부 IP는 도커가 설치된 호스트, 즉 내부망에서만 쓸 수 있는 IP이므로 외부와 연결될 필요가 있음
  • 컨테이너를 시작할 때마다 호스트에 veth(Virtual Ethernet) 이라는 네트워크 인터페이스를 생성
  • 도커는 각 컨테이너에 외부와의 네트워크를 제공하기 위해 컨테이너마다 가상 네트워크 인터페이스 을 호스트에 생성하며 인터페이스 이름은 veth 로 시작
  • veth 인터페이스는 사용자가 직접 생성할 필요가 없으며 컨테이너가 생성될 때 도커 엔진이 자동으로 생성
  • veth 인터페이스는 호스트가 갖고 있는 eth0,eth1 등과 연결되어 있음
  • docker0 브리지는 각 veth 인터페이스와 바인딩돼 호스트의 eth0 인터페이스와 이어주는 역할을 함

🐳 도커 네트워크 관련 명령어 정리

[1. docker network 목록 조회]

docker network ls

해당 명령어를 통해 로컬 도커에 설치된 네트워크 목록과 해당 네트워크에 드라이버까지 확인 가능합니다.

[2. docker network 상세 조회]

docker network inspect [도커 네트워크 ID or 도커 네트워크 이름]

Docker network ls 로 조회했던 네트워크 목록에서 이름이 bridge 인 네트워크 상세조회 결과입니다.
여기서 주목할 부분은 SubnetGateway 부분인데, 서브넷이 172.17.0.0/16 으로 설정되더 있으며, 호스트 내에서 컨테이너 생성시 해당 대역을 부여합니다.
이뿐만 아니라 해당 네트워크에 대한 다양한 정보를 확인할 수 있습니다.

[3. docker network 생성]

docker network create [만들 네트워크 이름]

test_network 라는 네트워크를 생성한 후 네트워크 목록을 조회한 결과입니다.
네트워크가 정상적으로 생성된 것을 확인할 수 있습니다 ❗️

네트워크를 생성할 때 네트워크 드라이버 또한 지정할 수 있습니다.

docker network create --driver = [네트워크 드라이버 이름][만들 드라이버 이름]

[4. 컨테이너 실행시 network 지정]

docker run -d ... --network=[네트워크 이름][컨테이너 이름]

앞서 만든 test_network01 이라는 네트워크를 이용해서 ubuntu 컨테이너를 실행시키겠습니다 ❗️

[5. 이미 실행중인 컨테이너에 network 지정]

docker network connect [네트워크 이름][컨테이너 이름]

해당 명령은 이미 실행중인 컨테이너에 네트워크를 지정한다는 점에서 4번과 다릅니다.

앞서 만든 test_network01 을 이미 실행중인 mysql 컨테이너에 지정해보겠습니다 ❗️

🐳 도커 네트워크 종류와 개념

도커 네트워크 드라이버는 NativeRemote 로 나뉩니다.

Native Drivers : Bridge,Host,None,Overlay 을 사용
Remote Drivers : 3rd party 드라이버로 외부에서 잘 만들어진 드라이버를 사용

도커 네트워크 드라이버는 단일 호스트 ,다중 호스트 로 분류할 수도 있습니다.

단일 호스트 네트워크 드라이버 : Bridge,Host,None
다중 호스트 네트워크 드라이버 : Overlay

[Bridge 네트워크]

포트를 연결해 컨테이너 애플리케이션의 Port 를 외부에 노출하는 방식이 bridge 네트워크 입니다.
아무런 네트워크 드라이버를 지정하지 않으면 default 로 docker0 이라는 bridge 네트워크 를 사용합니다.
또한 커스텀 bridge 네트워크 또한 생성가능합니다.

docker network create --driver=bridge my-bridge

앞서 보았던 컨테이너 네트워크 생성 명령어를 통해 my-bridge 라는 컨테이너 네트워크를 만들었습니다 ❗️

아무런 네트워크 설정을 하지 않은 채로, bridge 네트워크를 확인해보면 docker0 네트워크인 것을 확인할 수 있습니다.
IP 172.17.0.0을 사용하는 것을 확인할 수 있고 컨테이너를 네트워크 드라이버를 지정하지 않고 생성하면 해당 docker0 브릿지 네트워크를 사용합니다.

[Host 네트워크]

host 네트워크는 도커가 제공해주는 가상 네트워크 인터페이스(veth) 을 상요하는 것이 아니라 이름 그대로 host 의 네트워크에 붙어서 사용하는 개념입니다 ❗️
그래서 bridge 네트워크 처럼 포트 바인딩을 할 필요가 없으며 호스트 네트워크에 접속하면 컨테이너 또한 접속 가능합니다 🐳
간단하게 도커를 이용해서 host 네트워크를 이용해서 httpd 컨테이너를 구동시켜보겠습니다.

상단 이미지를 통해 해당 컨테이너에 포트가 따로 지정이 되지 않은 것을 확인할 수 있습니다.
호스트 네트워크에 붙어있기 때문에 별도의 포트가 할당되지 않는게 당연하겠죠? 😊

[None 네트워크]

none 네트워크 는 해당 컨테이너가 네트워크 기능이 필요 없을 때, 혹은 커스텀 네트워크를 사용해야 되는 경우가 있을 때 네트워크 드라이버를 none 으로 설정하고 사용할 수 있습니다 ❗️
즉 외부 네트워크와의 연결이 단절됩니다 🚫

docker run -d --network=none nginx:latest

해당 명령어를 통해 외부 네트워크와 단절된 Nginx 웹 서버가 컨테이너로 구동될 것이라는 것을 이해할 수 있습니다 ❗️

🐳 마치며

이번 포스팅에서는 도커의 네트워크에 대해서 알아보았습니다.
최대한 깊게 알아보려고 많은 시간을 투자했고 개인적으로 Network 에 대한 지식이 빈약해서 해당 포스팅 내용과 관련된 다양한 네트워크 기술들에 대해 공부하는 시간을 가졌습니다.

도커의 가상화 기술은 공부하면 할 수록 정말 혁신적인 기술인 것 같습니다.
다음 포스팅에서 도커에 대한 더 깊은 공부를 해보겠습니다 🔥 긴 글 읽어주셔서 감사합니다.


참고

6장. 도커 네트워크 구조
06. 도커 네트워크 (Docker Network)
DevOps/Docker [Docker] 도커 네트워크 이해하기
Infra/Docker[Docker] Docker Network 사용하기
쉽게 이해하는 네트워크 10. TCP/IP 네트워크 인터페이스 계층의 역할과 데이터 전송 (ft. 랜카드와 MAC 주소)
쉽게 이해하는 네트워크 7. TCP/IP 계층의 특징과 역할 및 프로토콜

profile
비즈니스가치를추구하는개발자
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 3월 20일

그러면 Overlay드라이버로 여러개의 콘테이너를생성하여 각콘테이너마다 네트워크를 구성하여 각콘테이너마다 vpn서버로 쓸수있나요?

답글 달기