Docker 톺아보기 19탄 - 컨테이너간 통신 (이론편)
오늘은 컨테이너 간의 통신에 대해 알아보도록 하자
컨테이너 간의 통신은 곧 컨테이너 간의 네트워크 연결을 의미한다
오늘의 목차다
1. 컨테이너는 어떻게 통신하나요?
2. 컨테이너 포트를 외부로 노출할 수 있나요?
3. 컨테이너 네트워크를 추가할 수 있나요?
4. 컨테이너끼리 통신은 어떻게 하나요?
출발해보자
== 1. 컨테이너는 어떻게 통신하나요? ==
위 그림은 컨테이너 네트워크의 기본적인 구조이다
큰 네모박스는 도커가 설치되어 있는 도커 호스트 시스템이다
이 시스템에서 도커 데몬이 start 되면 브릿지역할을 하는 docker0라는 도커 네트워크 인터페이스가 생성된다
docker0는 virtual ethernet bridge로써 172.17.0.0/16 값을 가지며, 브릿지 기능을 지원하는 가상 네트워크가 된다
이 브릿지는 호스트 시스템의 네트워크와 컨테이너 네트워크를 연결하는 역할을 한다
또한 docker0는 172.17.0.1의 ip를 가지고 컨테이너의 게이트웨이 역할을 한다
이 브릿지 기능을 지원하기 위해서 docker0는 내부적으로
NAT(Network Address Translation) 서비스와 포트포워딩 기능을 지원해주고 있다
(물론 직접 하는 것은 아니고 리눅스의 iptables로 지원해주는 것이다)
따라서 모든 컨테이너는 docker0를 통해서 외부와 통신하는 것이다
L2 통신을 지원하며, 컨테이너가 실행되면 172.17.X.Y로 컨테이너에 IP 주소가 할당된다
이 캡쳐는 현재 나의 도커 호스트 시스템의 네트워크 정보이다
현재 두 개의 컨테이너가 실행 중인 상황이다
== 2. 컨테이너의 포트를 외부로 노출할 수 있나요? ==
예를 들어, 웹 기반의 컨테이너 서비스를 제공하고 있다고 가정해보자
그렇다면 외부에서 컨테이너로 연결을 할 수 있게 하려면 Port Forwarding 기능을 사용해야 한다
현재 도커 호스트 안에 nginx와 app.js 컨테이너가 동작한다고 하면,
nginx는 웹 서버이다
nginx 컨테이너가 running 하면 172.17.0.2:80 을 열어서 서비스를 하게 된다
클라이언트가 nginx 웹 서버에 접속하려면 eth0라는 네트워크 인터페이스를 통해서만 접속이 가능하다
그렇기 때문에 eht0의 포트와 nginx 컨테이너의 포트를 짝지어줘서 하나의 길을 만들어주는 것이다
그러면 클라이언트는 eht0의 80포트를 통해 접속하면 그 길을 따라서 쭉 가다보면 nginx 컨테이너의 80포트로 접속이 가능한 것이다.
이런 식으로 포트포워딩은 컨테이너의 포트를 노출 시켜서 외부에서의 연결을 허용하는 것이다.
(단, 도커 호스트의 포트는 한개당 한번씩만 사용 가능하다)
$ docker run --name web -d -p 80:80 nginx:1.14
$ docker run --name appjs -d -p 80:8080 smlinux/appjs
$ iptables -t nat -L -n -v
== 3. 컨테이너 네트워크를 추가할 수 있나요? ==
이건 어떤 의미냐면
위의 네트워크 구성도에서 veth0, veth1과 같은 컨테이너 네트워크(IP 주소)가 자동으로 할당되는데,
이걸 우리가 원하는 IP 주소로 static하게 할당해주는게 가능하냐는 것이다
일단 기본적으로 docker0 인터페이스 안에 있는 네트워크에서는 static ip 할당이 불가능하다
다만 방법이 있긴 하다.
애초에 docker0 인터페이스가 아닌 새로운 네트워크 인터페이스를 만들어서 브릿지역할을 하도록 하면 된다.
그럼 그 브릿지에 연결된 컨테이너들은 static ip 할당이 가능하다
$ docker network create --driver bridge --subnet 192.168.100.0/24 --gateway 192.168.100.254 mynet
$ docker network ls
# 원래 사용방법(네트워크 자동할당)
$ docker run -d --name web -p 80:80 nginx:1.14
$ curl localhost
# 네트워크 수동할당
$ docker run -d --name appjs --net mynet --ip 192.168.100.100 -p 8080:8080 smlinux/appjs
$ curl localhost:8080
== 4. 컨테이너끼리 통신은 어떻게 하나요? ==
프론트단에 있는 컨테이너와 백단에 있는 컨테이너가 서로 통신을 해야 데이터도 교환할 수 있을 거다
wordpress라는 웹 페이지 제작을 쉽게 해주는 apache 웹 서버가 내장된 애플리케이션이다
그리고 wordpress에서 만들어진 데이터는 모두 mysql 데이터베이스에 저장되도록 되어있다
$ docker run -d --name mysql -v /dbdata:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=wordpress -e MYSQL_PASSWORD=wordpress mysql:5.7
$ docker run -d --name wordpress --link mysql:mysql -e WORDPRESS_DB_PASSWORD=wordpress -p 80:80 wordpress:4
위 명령에서 --link 옵션은 같은 호스트 내의 컨테이너를 연결시켜줄 때 사용한다
--link [연결시킬 컨테이너의 이름]:[별칭]
이런 구조이다
컨테이너의 네트워크를 자동으로 할당하면 컨테이너를 재시작할 때, 네트워크 주소가 변경되는 경우가 있다
하지만 --link 옵션은 네트워크 주소 기반이 아닌 컨테이너 이름 기반이기 때문에 네트워크가 변경되어도 문제가 없다
이렇게 컨테이너의 네트워크에 대해서 알아보았다
다음 시간에는 실습을 해보자
고생 많았고 모두 새해 복 많이 받자!!
뿅!
