여러 개의 장치들이 서로 연결되어서 정보를 주고받을 수 있는 시스템이다.인터넷에서 정보를 검색할 때도 네트워크를 통해서 정보를 주고받을 수 있다. 네트워크는 기계와 기계 사이를 랜선이라는 케이블을 통해 물리적으로 연결한다. 이 물리적인 케이블로 전기신호를 통해서 정보를 주고받을 수 있다. (like 집과 도로)
전기 신호로 만들어진 정보가 인터넷 선을 타고 기기들 사이를 이동할 수 있다. 실제 바다 건너 미국에 있는 컴퓨터의 정보를 받아올 때도 아시아와 미국을 연결하는 해저 케이블을 통해 정보를 받아온다.
즉, 전 세계의 전자기기들은 물리적인 인터넷 선으로 연결되어 있고, 이 선들이 그물망처럼 촘촘히 짜여져 있다고 해서(net + work) 네트워크라고 부르게 되었다.
네트워크에서 어떤 정보를 보내기 위해서는 목적지의 주소가 필요하다. IP 주소로 장치들의 위치를 관리한다. 따라서 컴퓨터가 인터넷에 연결될 때 IP주소를 할당 받는다. 이 IP 주소를 활용해서 컴퓨터나 기계들이 인터넷에서 서로를 찾고 통신할 수 있다. IP 주소는 8바이트에서 3자리 숫자 4개 조합으로 만들어진 주소이다. (IPv4)
범위의 고유한 값으로는 0.0.0.0 ~ 255.255.255.255 (이로 조합할 수 있는 IP주소는 43억개, 하지만 현재 거의 고갈된 상태.. IPv6가 나옴)이 있다. 주소 역할을 하려면 고유해야하기 떄문에 다른 IP와 중복될 수 없다. IP주소는 각각의 통신사가 관리한다. 고정적인 IP를 받아서 사용할 수 있으며, 변경될 수 도 있다. 일반적으로 가정용 인터넷은 동적 IP를 사용하기 때문에 시간이 지나면서 집에 할당된 IP가 바뀔 수도 있다.
보통 통신사의 인터넷에 가입하면 회선당 하나의 IP를 할당받아 사용한다. 본인 PC에 할당된 IP를 확인해보고 ping 명령어를 통해 다른 서버로 인터넷 신호를 보낼 수 있다. (터미널에서 ping 1.1.1.1 하면 상대방 서버에서 응답이 있는지 확인하는 명령이다.)
→ 네트워크는 기기 간의 정보를 주고받기 위한 통신망이다.
→ 전 세계의 네트워크 신호는 IP 주소 체계를 사용해서 원하는 목적지로 찾아갈 수 있다.
회선당 공인IP가 하나씩 할당되는데, 하나의 인터넷 회선으로 스마트폰, 노트북, TV등 다양한 기기로 인터넷을 사용하고 있다. 이처럼 하나의 IP로 여러 기기가 인터넷을 사용하려면 사설 IP를 활용해야한다.
IP는 공인IP와 사설IP가 있다.
공인 IP는 집 주소처럼 인터넷 상에서 고유하다. 이 IP주소를 통해서 전세계의 기기들과 데이터를 주고받을 수 있다.
사설 IP는 집 내부에서 방 번호를 나누는 것처럼 하나의 공인 IP를 나눠서 정의된다. 이 공인 IP안에서 사설 IP로 나눌 때는 네트워크 장비가 필요하다. 가정에서 일반적으로 공유기를 사용한다. (공유기의 1개의 WAN 포트는 외부에서 들어오는 인터넷 신호를 연결하고, 여러개의 LAN 포트를 통해 사설 IP(인터넷 신호)를 분배한다.) 사설IP는 공유기처럼 하나의 네트워크 장비 안에서만 고유하다.
→ IP는 외부에서 사용하는 공인 IP와 내부에서만 사용하는 사설 IP로 관리할 수 있다. 공인 IP를 공유기에 연결해서 여러 개의 사설 IP로 분리했고, 이 사설 IP들은 공유기에 연결되어 있는 TV, 컴퓨터, 스마트폰이 하나씩 받아서 사용할 수 있다. 이렇게 사설 IP를 사용하면 하나의 공인 IP만 가지고도 여러 기기들로 인터넷을 나눠 사용할 수 있다.
→ 서버에 네트워크 인터페이스가 장착되어 있고, 이 네트워크 인터페이스에 할당된 IP로 데이터를 주고 받는다.
하지만 서버는 여러 개의 소프트웨어가 실행된다. 이 중 어떤 소프트웨어로 데이터를 전달할지 지정하는 것이 바로 포트 넘버이다. IP뒤에 :포트번호 로 소프트웨어를 지정할 수 있다. 포트는 물리적으로 존재하진 않고, 서버 안에서 정의해서 사용할 수 있다. 네트워크를 사용하는 프로그램은 실행될 때 자신이 사용할 포트를 지정할 수 있다.
서버에서 실행중인 웹서버는 80(http), 443(https), SSH 통신은 22, FTP (파일 통신) 21 포트를 지정해야 한다. 이처럼 사전에 약속된 포트를 Well-Known Port라 한다.
애플리케이션 8080 포트처럼 개발자가 자신의 소프트웨어가 사용할 포트를 직접 지정할 수도 있다.
네트워크 통신은 크게 OutBound, InBound로 나눌 수 있다.
외부서버와 내부서버의 통신
외부의 공인 IP와 내부의 사설 IP의 통신은 어떻게 될까?
→ NAT와 포트포워딩 기술
위의 경우, 사설망의 안쪽에 있는 서버에서 외부서버로 요청이 전달되었다가 외부 서버에서 응답이 돌아올 때의 트래픽 처리이다.
바깥쪽 서버에서 사설 IP로 직접 요청을 보내는 인바운드 요청의 경우엔 요청을 보낼 때 NAT 테이블의 규칙에 맞게 자동생성되는 공인포트번호로 지정해서 요청을 전달하는 방법도 있다. 하지만 보통은 외부에서 사내망으로 요청을 보내는 경우에는 포트를 랜덤으로 사용하는 것보다 미리 포트를 지정해 두는 것이 자연스럽다.
외부에서 사내 서버를 접근한다는 것은 사내 서버에서 제공하는 특정 서비스를 사용한다는 것을 의미한다. 내부 서버1이 웹서비스를 제공하면 80포트, 내부 서버 2번이 데이터베이스를 제공하면 5432포트로 접근하는 것처럼 랜덤한 포트가 아니라 사전에 정의되어 있는 포트를 제공하는 것이 더 자연스럽다.
NAT 테이블은 동적으로 정보를 관리하기 때문에 외부에서 서버를 접근하는데 혼란이 생길 수도 있다.
따라서 외부에서 사내망으로 접근할 경우 포트포워딩이라는 기술을 사용한다.
DNS 서버로 주소의 IP검색
nslookup dns주소
nslookup google.com
→ 내부 DNS에 google.com 도메인 정보가 없으면 사내망 서버에서는 google.com 도메인 정보를 사용할 수 없다. 하지만 이 부분은 내부 DNS 설정에 따라 다르게 작동한다. 내부 DNS 서버에 데이터가 없으면 내부 DNS 서버가 직접 외부 DNS 서버로 자기한테 없는 값을 물어볼 수 있다. (외부 연동 설정 여부에 따라 다르다.)
→ 서버 한 대를 여러 컨테이너로 격리하는 기술이다.
→ 서버 한 대 안에서 여러 네트워크를 구성하는 기술이다.
→ 네트워크 망 안에서 컨테이너들이 서로 통신할 수 있고, 내부의 컨테이너와 바깥의 서버와도 통신할 수 있다.
따라서 가상 네트워크에 대해서 얘기할 때는 서버 한 대 안에 초점을 맞춰야 한다. 실습하는 PC도 가상화 기술을 사용하는 서버 한 대의 역할을 하기 때문에 구조도에 표시된 서버를 실습용 PC라 생각하면 된다.
가상 네트워크 아키텍처에서 바깥에 물리 네트워크가 어떻게 구성되어 있는지는 중요하지 않다. 어쨌든 물리 서버에서는 네트워크 인터페이스를 통해 공인 IP나 사설 IP가 할당되어 있을 것이다.
도커는 가상네트워크 기술을 활용해 컨테이너의 네트워크를 구성한다. 가상 네트워크는 실제로 인터넷 선이나 공유기가 없이 오직 한 대의 서버 내에서 논리적으로 정의되어 있는 네트워크이다.
가상의 네트워크 브릿지 네트워크와 가상의 공유기인 도커 제로를 생성한다.
→ 도커의 브릿지 네트워크는 컨테이너들에게 IP를 할당해주고 컨테이너들끼리 통신할 수 있도록 만들어 준다.
도커에서 컨테이너 실행하면 도커는 브릿지 네트워크의 IP주소 범위 내에서 컨테이너에 가상의 IP를 할당한다.
같은 브릿지에서 생성된 네트워크는 브릿지를 통해서 통신할 수 있다. (컨테이너간의 통신 전달)
→ 논리적으로 네트워크를 구성하는 기술을 SDN(Software Defined Network) 라 한다.
→ 호스트 OS에는 실제 존재하는 하드웨어인 물리 인터페이스 1개와 소프트웨어로 만들어진 가상의 인터페이스가 5개 만들어진 상태이다.
→ 이때 가상의 인터페이스로 전달되는 네트워크 신호는 각각의 인터페이스로 해당되는 컨테이너로 전달된다. ex) OS에서 Veth2 인터페이스로 신호를 보내면 Veth2 인터페이스는 컨테이너 2번으로 네트워크 신호를 전달한다.
→ 컨테이너끼리 요청을 보낼 때는 Veth1 → Veth2 인터페이스 여야 한다. 물리네트워크의 경우 도착지 IP에 맞게 네트워크를 통해 기기에 전달하는 것을 네트워크 장비들이 해준다. 하지만 가상 네트워크의 경우 별도의 장비가 없기에 소프트웨어적으로 트래픽을 전달해줘야 한다.
→ 가상의 인터페이스 간의 네트워크 패킷을 전달하는 규칙은 호스트OS의 커널 소프트웨어인 iptables에 정의된다.
→ 도커는 컨테이너 통신을 위해 브릿지 네트워크를 정의하고, 호스트 OS의 가상 인터페이스를 생성한다. 그리고 호스트 OS의 iptables 규칙을 관리하면서 가상 인터페이스들 간의 통신 규칙을 만든다. 따라서 사용자는 별도의 설정을 하지 않아도 같은 브릿지 네트워크에서 생성된 컨테이너들은 서로 통신할 수 있다.
→ 또한, 도커는 가상 네트워크 내부에서 여러 개의 브릿지 네트워크를 관리할 수 있다. 브릿지 네트워크 단위로 분리해 특정 컨테이너들끼리는 통신이 되지 않도록 구성할 수도 있다.
네트워크 리스트 조회
docker network ls
네트워크 상세 정보 조회
docker network inspect 네트워크명
네트워크 생성
docker network create 네트워크명
네트워크 삭제
docker network rm 네트워크명
도커를 설치하면 기본적으로 하나의 브릿지 네트워크가 있다.
docker network ls
docker network inspect bridge
docker network create --driver bridge --subnet 10.0.0.0/24 --gateway 10.0.0.1 second-bridge
docker run -d --name ubuntuA devwikirepo/pingbuntu
docker run -it --name ubuntuB devwikirepo/pingbuntu bin/bash
docker run -it --network second-bridge --name ubuntuC devwikirepo/pingbuntu bin/bash
docker ps 하면 셋다 실행 중임을 알 수 있다.
docker container inspect ubuntuA → 컨테이너의 네트워크 정보를 조회할 수 있다.
ubuntuA, ubuntuB는 Gateway는 동일, IPAddress만 다르다.
ubuntuC는 Gateway, IPAddress가 다르다.
ping 명령어를 통해 확인해보면 ubuntuA, ubuntuB끼리는 통신 가능, ubuntuC는 불가능하다.
HostOS로의 네트워크 접근을 컨테이너로 포트포워딩
docker run --name 컨테이너이름 -p 호스트OS포트:컨테이너포트 이미지이름
→ 왼쪽은 호스트 OS 포트, 오른쪽은 컨테이너가 사용하는 포트를 지정한다.
→ 도커가 실행 중인 서버의 포트를 사용해서 컨테이너로 접근할 수 있다.
가상 네트워크 안에서 컨테이너를 실행하면 컨테이너들끼리는 통신이 가능하다. 하지만 사용자 PC인 호스트OS나 가상 네트워크 바깥에 있는 서버에서 이 컨테이너로 접근하려면 포트포워딩 기술을 사용해야 한다.
Nginx와 DB 컨테이너가 실행 중이고, 172.17.0.2, 172.17.0.3 IP로 실행 중이라고 하면, 공인망에서 사설망으로 네트워크 신호를 보낼 땐 NAT와 포트포워딩 기술을 활용하듯 여기도 동일하게 사용된다.
따라서 Nginx와 DB 컨테이너는 바깥쪽 192.168.0.20, 192.168.0.30로 네트워크 신호를 보낼 수 있다. NAT은 가상 네트워크가 알아서 설정하기 때문에 특별히 지정하지 않아도 내부의 컨테이너는 바쪽 외부망을 통해 다른 서버로 접근할 수 있다. 하지만 다른 서버로 접근하려면 실제로 도커가 실행 중인 물리 서버나 실습용 PC가 물리적인 네트워크로 연결되어 있어야지만 접근이 가능하다.
외부에서 접근할 경우 192.168.0.10에서 포트포워딩을 해서 특정 포트로 접근했을 때 사용자가 지정한 컨테이너로 전달하도록 포트포워딩을 등록해야 한다. PC의 IP인 192.168.0.10의 8001 포트로 요청을 보내면 Nginx 컨테이너의 80포트로 요청이 전달된다. 호스트OS의 포트는 아무거나 지정해도 상관 없지만 중복은 안된다.
docker run -d --name nginx nginx
docker container inspect nginx
→ 컨테이너 IP는 172.17.0.2, 포트포워딩을 지정하지 않았기 때문에 컨테이너 IP를 치면 아무 응답이 없다. 172.17.0.2는 가상 네트워크망의 IP 대역이기 때문에 실제로 물리 네트워크에 속해 있는 호스트OS나 다른 서버에서는 접근할 수 없다.
→ 172.17.0.2는 내부의 가상 네트워크에서만 사용되는 IP이고, 실제로 물리적인 네트워크에서 접근하기 위해서 포트포워딩기술을 사용하는 것이다.
포트포워딩을 설정한 nginx 실행
docker run -d -p 8001:80 --name nginx2 nginx
docker run -d -p 8002:3000 --name redColorApp --env COLOR=red devwikirepo/envnodecolorapp
docker run -d -p 8003:3000 --name blueColorApp --env COLOR=blue devwikirepo/envnodecolorapp
로컬 호스트 말고 PC의 IP를 사용해서 접근해도 된다.
ifconfig en0 → 본인의 IP확인
본인IP:포트번호 로 접속해도 들어가진다.
이 IP는 사설 IP이기 때문에 사설망의 IP를 사용하는 기기들은 본인IP:포트번호로 접근했을 때 이 웹서버 컨테이너로 접속할 수 있다.
docker run -d -p 8003:3000 --name yellowColorApp --env COLOR=yellow devwikirepo/envnodecolorapp
docker run -d -p 8004:3030 --name greenColorApp --env COLOR=green devwikirepo/envnodecolorapp
docker rm -f nginx redColorApp blueColorApp yellowColorApp greenColorApp → 실습 컨테이너 모두 삭제
정리
토커는 컨테이너들이 기본적으로 사용할 수 있는 DNS 서버를 제공한다. DNS 서버에는 IP주소와 도메인명이 저장되어 있다. 여기서 Domain은 컨테이너 이름으로 자동 저장된다. 따라서 컨테이너는 기본적으로 컨테이너의 IP가 아닌 컨테이너의 이름으로 서로 통신할 수 있다.
이 DNS서버는 외부의 DNS 서버와 연동되어 있어 구글같은 외부 도메인도 사용할 수 있다. 하지만 기본으로 생성되는 브릿지 네트워크는 DNS 기능이 제공되지 않고, 사용자가 직접 생성한 브릿지만 컨테이너의 이름을 통해서 통신할 수 있다.
→ 도메인 주소를 사용하면 IP주소가 바뀌는 환경에서 다른 서버들이 영향받지 않고 연결이 일관적으로 이뤄진다는 장점이 있다.
docker network create --driver bridge --subnet 10.0.0.0/24 second-bridge
docker run -it --network second-bridge --name containerA devwikirepo/pingbuntu bin/bash
cat /etc/resolv.conf
ping containerB
docker run -d --network second-bridge --name containerB devwikirepo/pingbuntu
docker inspect containerB
ping containerB
docker rm -f containerB
ping containerB
docker rm -f containerA
docker network rm second-bridge
→ 실습 마치기
docker network create leafy-network
→ leafy-network라는 브릿지 네트워크 생성, 새롭게 네트워크 만든 이유는 기본 네트워크는 DNS 기능을 제공하지 않기 때문이다.
→ DNS 사용하지 않으면 SpringBoot에서 DB에 접근할 때 name(도메인)이 아닌 IP를 통해 접근해야 한다. but IP는 자동으로 할당되기 때문에 DB 컨테이너가 재시작되면 IP도 변경될 수 있다.
docker run -d --name leafy-postgres --network leafy-network devwikirepo/leafy-postgres:1.0.0
→ leafy-network로 네트워크 지정
→ leafy-postgres가 도메인 명인 컨테이너 실행
docker run -d -p 8080:8080 -e DB_URL=leafy-postgres --network leafy-network --name leafy devwikirepo/leafy-backend:1.0.0
→ 8080포트 포트포워딩
→ DB접속 URL을 postgres 컨테이너의 이름으로 지정
docker run -d -p 80:80 --network leafy-network --name leafy-front devwikirepo/leafy-frontend:1.0.0
→ leafy-network로 네트워크 지정
→ 프론트엔드 실행할 때는 80포트 포트포워딩
포트포워딩이 되어 있지 않은 leafy-postgres는 사용자의 PC에서 접근 불가이다. 포트포워딩이 되어있는 leafy, leafy-frontend는 실습PC의 IP의 80, 8080 으로 접근가능하다. 실습 PC는 localhost, 127.0.0.1, PC의 IP에 포트 추가하면 접근 가능하다. 실습 PC와 같은 네트워크 망에 있는 다른 기기들은 PC의 IP에 포트를 추가하면 접근 가능하다.
이렇게 외부에 접근이 필요한 컨테이너는 포트포워딩을 통해서 호스트PC의 IP를 컨테이너와 연결할 수 있고, DB같이 직접 연결할 필요가 없는 컨테이너는 포트포워딩을 설정하지 않음으로써 컨테이너들끼리만 통신할 수 있도록 설정한다.
docker ps
2. 구성 환경 삭제
docker rm -f leafy-front leafy leafy-postgres