Docker Networking
도커 네트워킹 다루기
[목표]
Dokcer 컨테이너 및 서비스가 서로 연결하고 통신할 수있도록 한다.
네트워크 드라이버 종류
bridge network: 기본 네트워크 드라이버. 동일한 Docker 데몬 호스트에서 실행되는 컨테이너에 적용되며, 다른 Docker 데몬 호스트에서 실행되는 컨테이너 간 통신의 경우 OS 수준에서 라우팅을 관리하거나 오버레이 네트워크를 사용해야한다.host network: standalone형 컨테이너의 경우 컨테이너와 Docker 호스트 간의 네트워크 격리를 제거하고 호스트의 네트워킹을 직접 사용.overlay network: 여러 Docker 데몬을 함께 연결하여 스웜에서 서비스가 서로 통신 할 수 있게한다. 또한 오버레이 네트워크를 사용하여 [스웜 서비스와 standalone 컨테이너 간] 또는 [서로 다른 Docker 데몬에 있는 두 개의 standalone 컨테이너간] 통신을 가능하게 한다.macvlan: 컨테이너에 MAC주소를 할당하여 네트워크의 물리적인 장치로 나타낼 수 있게한다.
브릿지 네트워킹
동일한 Docker 호스트에서 두 개의 다른 컨테이너를 실행시키고 서로 통신하기
-
현재 docker network 살펴보기
docker network ls가장 기본적으로 생성되어있는 네트워크
bridge,host,none이 보인다. -
alpine컨테이너를 두개 실행시킨다.docker run -d -i -t --name alpine1 alpine ash docker run -d -i -t --name alpine2 alpine ash컨테이너가 작동중인지 확인한다.
docker container ls -
브릿지 네트워크에 연결된 컨테이너가 있는 확인한다.
docker network inspect bridgecontainers를 보면 현재 alpine1, alpine2가 따로 설정한적 없지만 연결되어 있는 모습이 보이고 각각에 부여된 IP주소와 상단 부분에 네트워크의 서브넷과, 게이트웨이가 보인다.
-
docker attach 명령어를 통해 alpine1 컨테이너에 연결한다
docker attach alpine1ip addr show 명령어를 사용하여 alpine1 컨테이너의 네트워크 인터페이스를 표시한다.
ip addr show -
alpine1에서
google.com으로 핑을 날려볼 것이다.ping -c 2 google.com -
다음으로 두번째 컨테이너인 alpine2(172.17.0.3)쪽으로 핑을 날려본다.
ping -c 2 172.17.0.3이번에는 아이피가 아닌 alpine2 이름으로 핑을 날려본다.(실패하는게 정상)
ping -c 2 alpine2 -
ctrl+p,ctrl+q를 통해 alpine1 컨테이너를 중지시키지 않고 빠져나와, alpine2에 접속하여 위의 과정들을 다시해봐도 좋다. -
두 개의 컨테이너를 중지시키고 제거한다.
docker container stop alpine1 alpine2 docker container rm alpine1 alpine2
도커에서는 브릿지 네트워크를 production환경으로는 추천하지 않는다라고 하고있다.
user-defined 브릿지 네트워크
이번에는 디폴트 네트워크(NAME=bridge)가 아닌 우리가 만들어낸 alpine-net네트워크에 컨테이너들을 시작할것이다. 또 bridge네트워크에도 컨테이너를 하나 생성한 후 두 개의 네트워크들을 살펴본다.
-
alpine-net네트워크 만들기docker network create --driver bridge alpine-net -
네트워크가 생성되었는지 확인해본다.
docker network lsdocker network inspect alpine-net여기서 보아야 하는 것은 게이트웨이의 주소이다. 전의 디폴트 네트워크의 게이트웨이 주소는 172.17.0.1이였고, 현재는 바뀐것을 알수있다.
-
컨테이너를 생성해보자. 또
docker network connect명령어를 통해서alpine4를 브릿지 네트워크에 연결한다.docker run -dit --name alpine1 --network alpine-net alpine ash docker run -dit --name alpine2 --network alpine-net alpine ash docker run -dit --name alpine3 alpine ash docker run -dit --name alpine4 --network alpine-net alpine ash docker network connect bridge alpine4 -
bridge네트워크와alpine-net네트워크를 다시 확인해보자docker network inspect bridge컨테이너에 alpine3과 alpine4가 연결되어있어야 한다.
docker network inspect alpine-netalpine1, alpine2, alpine4가 연결되어 있어야 한다.
-
alpine-net과 같이 유저가 정의한 네트워크에서는 IP통신뿐만 아니라 위의 브릿지 네트워크에서 실패한 컨테이너 이름으로 통신하는 것 또한 가능하다. alpine1에 접속하여 테스트해보자.docker container attach alpine1 -
반면
alpine1에서alpine3으로 연결을 시도하면 실패할 것이다.ping -c 2 alpine3뿐만 아니라 IP주소로 연결하는 것조차 되지 않는다.
ctrl+p,ctrl+q를 통해서alpine1에서 detach하자 -
alpine4를 살펴보자. 이 컨테이너는alpine-net뿐만 아니라bridge네트워크에도 연결되어 있다. alpine3 컨테이너를 이름으로 부를수는 없지만 IP주소로 연결은 가능하다. -
컨테이너를 중지하고 삭제하자.
docker container stop alpine1 alpine2 alpine3 alpine4 docker container rm alpine1 alpine2 alpine3 alpine4 docker network rm alpine-net
호스트 네트워킹
Docker 호스트의 네트워크에 직접 바인딩하는 독립형 컨테이너
- 호스트 네트워킹은 오직 리눅스 위에서만 작동한다. Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server는 지원되지 않는다.
-
컨테이너 생성
docker run --rm -d --network host --name my_nginx nginx–rm 태그는 컨테이너가 종료 혹은 중지 될때 제거된다는 것을 의미한다.
-
80포트를 이용하여 nginx에 접속한다.
-
현재 로컬의 네트워크 인터페이스를 보도록 한다.
ip addr shownetstat명령어를 통해서 80번 포트가 프로세스에 바운드됬는지 확인한다.sudo netstat -tulpn | grep :80호스트 네트워킹에 직접적으로 바인딩되었음을 알 수 있다.
-
컨테이너를 중지한다. 생성시 –rm 명령어로 인해 자동적으로 컨테이너는 삭제될것이다.
docker container stop my_nginx
오버레이 네트워킹
디폴트 오버레이 네트워크 사용하기
- 이번 튜토리얼을 진행하기 위해서는 3대가 필요하다. 나는 EC2를 3개 생성하여 진행하였다. (manager, worker-1, worker-2)
- 3개를 만든 후에는 각각에 도커 설치를 진행한다.
- EC2를 사용하는 경우라면 2377,7946,4789포트의 TCP/UDP를 열어주도록 한다.
Swarm 생성
이 과정을 통해서 3개의 호스트가 스웜에 join하고 오버레이 네트워크를 이용하여 연결시킨다.
-
Manager역할을 맡을 호스트에서 다음의 명령어를 실행시킨다.
docker swarm init명령어를 통해 나온 출력물을 보면 swarm에 join하기 위한 명령어를 보여줄것이다. 이를 통해 다른 호스트에서 조인해보자.
-
worker-1 역할을 맡을 호스트에서 다음의 프린트를 실행시킨다.
docker swarm join --token <TOKEN> IP-ADDRESS:PORT권한 관련해서 뭐라하면
sudo붙이고 실행하세요. 타임아웃이 날 경우 manager 역할을 맡은 호스트에서 2377포트를 허용하도록 했는지 확인하세요. -
마찬가지로 worker-2에서도 위의 명령어를 실행시킵니다.
-
manager 노드로 돌아가서 아래의 명령어를 통해 swarm 에 조인되어 있는 노드들을 확인합니다. 이 때 3개(
자신,worker-1,worker-2)가 나와야 정상입니다.docker node ls -
manager 노드에서
ingress라는 이름을 가진overlay네트워크와docker_gwbridge라는브릿지네트워크가 생성되었는지 확인합니다.docker network lsdocker_gwbridge : manager와 worker로부터 트래픽이 움직일 수 있도록 ingress 네트워크를 도커 호스트 네트워크 인터페이스에 연결.
서비스 만들기
-
manager 노드에서
nginx-net라 불리는 새로운 overlay 네트워크를 만든다.docker network create -d overlay nginx-net이 명령어는 다른 노드에서 실행하지 않더라도 서비스 작업을 실행하기 시작하면 이러한 네트워크 생성 작업이 자동으로 생성된다.
-
manager 노드에서 5개의
nginx서비스를 복사하고 이를nginx-net에 연결한다. 모든 서비스 작업 컨테이너들은 어떠한 포트를 열지않고도 통신할 수 있다.docker service create \ --name my-nginx \ --publish target=80,published=80 \ --replicas=5 \ --network nginx-net \ nginx -
docker service ls를 실행시켜 모니터링해봅니다. -
모든 노드에서
docker network inspect nginx-net을 명령어를 치고 컨테이너와 피어 부분을 본다. 컨테이너에 엔드포인트와 my-nginx.(5이하의 숫자)가 각각 있음을 본다. -
docker service inspect my-nginx를 통해 서비스가 사용중인 엔드포인트,포트 등의 정보를 확인한다. -
nginx-net-2라는 새로운 네트워크를 생성하자 그리고nginx-net을 대신하여 네트워크의 서비스를 업데이트한다.docker network create -d overlay nginx-net-2docker service update \ --network-add nginx-net-2 \ --network-rm nginx-net \ my-nginx -
docker service ls를 실행하여 서비스가 업데이트 되었고 모든 작업이 다시 배포되었는지 확인한다. 또한docker network inspect nginx-net을 통해 어떠한 컨테이너도 네트워크에 연결되어있지 않다는 것을 확인하다. 또한 이것을nginx-net-2에서도 확인해봅니다. -
네트워크와 서비스를 정리한다. 이 명령어를 통해 manager노드가 worker노드들에게 마찬가지로 지시할것이다.
docker service rm my-nginx docker network rm nginx-net nginx-net-2
user-defined 오버레이 네트워크 사용
-
user-defined 오버레이 네트워크 생성하기
docker network create -d overlay my-overlay -
서비스를 실행시킨다.
docker service create \ --name my-nginx \ --network my-overlay \ --replicas 1 \ --publish published=8080,target=80 \ nginx:latest -
docker network inspect my-overlay명령어를 통해서 my-nginx 서비스 작업이 연결되었음을 확인한다. 어디에 생성됬을까? ㅎㅎ -
네트워크와 서비스를 제거한다
docker service rm my-nginx docker network rm my-overlay
Standalone 컨테이너에 오버레이 네트워크 사용
이번 예제는 2개의 노드를 사용하여 진행한다.
- host1 : swarm manager
- host2 : swarm worker
-
host1에서 스웜을 초기화하여 생성한다.host2에서 해당 스웜에 조인한다.이미 작업한 내용이기에 그냥 지나간다.
-
manager노드에서test-net이라 불리는 네트워크를 생성한다.docker network create --driver=overlay --attachable test-net -
host1에서-it플래그를 통해서 컨테이너alpine1을 시작한다.docker run -it --name alpine1 --network test-net alpine -
host2에서 이용 가능한 네트워크 리스트를 본다. 아직test-net네트워크가 존재하지 않는 것을 알 수 있다. -
host2에서alpine2이름을 가진 컨테이너를-d와-it를 이용하여 실행시킨다.docker run -dit --name alpine2 --network test-net alpine -
host2에서 다시 네트워크 리스트를 본다. 이번에는 네트워크가 존재할 것이다. -
host1으로 돌아가alpine2에게 핑을 날려보자.ping -c 2 alpine2나의 경우에는 뭘 잘못했는지 이상하게 여기서부터 통신이 안된다. ,,,,
-
아무튼 내가 잘못한거지 여기서는 잘 실행된다고 하니 뭐..
host2에서도host1핑 날려보고 -
각 노드에서 컨테이너 중지, 삭제, manager에서는 test-net 네트워크 삭제까지 해준다.
마치며
- 오늘은 도커 네트워킹을 사용하여 각 컨테이너 간의 통신에 대하여 알아보았다. 이제 이를 통해서 젠킨스와 도커를 이용한 배포를 이어서 할 수 있을듯 하다.