📂 목차
📚 본문
Docker Network
컨테이너끼리 혹은 컨테이너와 외부 간에 통신을 가능하도록 하는 가상 네트워크 환경임을 보았다. 도커가 자체적으로 가상 NIC, 가상 스위치, 라우팅 등을 구축한다.
기본 네트워크 타입들
bridge driver
docker run 시 아무 설정이 없다면 자동으로 붙는 네트워크이며, 단일 서버 내 컨테이너끼리 통신이 가능하다. NAT 기반으로 외부 <-> 컨테이너 간에 통신을 제어한다.
docker network ls
# bridge / host / none 등이 보임
docker run -d --name db --network my_net mysql
docker run -d --name app --network my_net myappmy_net 이라는 사용자 정의 네트워크를 만들어 컨테이너들을 등록한다.
사용
- 단일 호스트 환경에서 여러 컨테이너를 함께 운영할 때
- 컨테이너끼리 서로 통신은 필요하지만, 기본적인 격리는 유지하고 싶을 때
- 개발 또는 테스트 환경처럼 일반적인 워크로드에서 기본 설정을 그대로 사용하고 싶을 때
host driver
컨테이너가 호스트의 네트워크 스택을 그대로 사용할 때, 호스트와 컨테이너의 포트 구분이 없이 사라진다. 성능은 가장 빠르다.
# localhost:80 <- nginx 바로 동작
docker run --network host nginx- 네트워크 성능(레이턴시/처리량)이 매우 중요한 서비스
- NAT(Network Address Translation) 오버헤드를 없애고 싶은 경우
- 컨테이너가 호스트의 IP를 그대로 사용해야 하는 특수한 상황
포트 충돌 관리가 힘듦
none driver
네트워크가 없는 컨테이너를 만들고 싶을때 사용하며, 외부 연결과 완전히 차단해야 할 때 사용한다.
docker run --network none myimageoverlay driver
여러 서버에 걸친 컨테이너 끼리 통신이 가능하다. Docker Swarm, Kubernetes 등이 사용하는 방식이다.
# overlay 네트워크는 Swarm이나 Kubernetes 클러스터 환경에서 사용
# 단일 호스트에서는 의미가 없음
# Docker Swarm 초기화 필요
docker swarm init
# 그 다음 overlay 네트워크 생성 가능
docker network create -d overlay myoverlay
# Swarm 서비스로 배포
docker service create \
--name web \
--network myoverlay \
--replicas 3 \
nginx - 여러 물리 서버(호스트)를 하나의 가상 네트워크로 묶음
- VXLAN 기술 사용
- 단일 호스트 개발 환경에서는 거의 안 씀
컨테이너를 만든 후 만든 컨테이너에 대한 docker inspect 를 사용으로 IP를 볼 수 있다.
docker inspect web1 | grep IPAddress출력: “IPAddress”: “172.17.0.2”
포트 매핑
컨테이너는 기본적으로 외부에서 직접 접근할 수 없는 격리된 공간에서 실행되는데, 외부에서 컨테이너에 접근하려면 포트 매핑을 통해 호스트의 특정 포트를 컨테이너 내부 포트와 연결해줘야 한다.
-p [호스트IP:]호스트포트:컨테이너포트[/프로토콜]
# 예시
-p 8080:80 # 호스트 8080 -> 컨테이너 80
-p 127.0.0.1:8080:80 # localhost:8080만 접근 가능
-p 3306:3306/tcp # TCP 명시 (기본값)
-p 53:53/udp # UDP 포트 매핑
-p 8080-8090:8080-8090 # 포트 범위 매핑p 옵션을 여럿 써서 외부에 다수의 포트와 연결시킬 수도 있다.
포트를 연결시키기 전에
netstat -tuln | grep 8080으로 사용하고 있는지 확인해준다.
Docker DNS
컨테이너가 많아질수록 IP 가 계속 바뀌고, 포트 매핑 만으로는 서비스 간의 연결을 관리하기 힘들다. 도커는 이를 해결하기 위해 내장 DNS 기반 서비스 디스커버리 기능을 제공하며, 특히 사용자 정의 bridge 네트워크를 사용할 때 자동으로 컨테이너 이름을 DNS 로 등록하여 IP 를 몰라도 서로 통신할 수 있게 된다.
컨테이너 이름 기반 통신(DNS)
Docker 의 user-defined bridge 네트워크는 자체 DNS 서버를 내장하고 있으며, 이 DNS 서버는 같은 네트워크에 속한 컨테이너 이름을 IP 로 실시간으로 변환해준다.
- 각 컨테이너는
--name으로 지정된 이름으로 접근이 가능 - 같은 네트워크 내에서만 DNS 해석 가능
/etc/resolv.conf에 등록된 Docker DNS(127.0.0.11) 가 조회 수행- (컨테이너 이름) = (서비스 이름(Service Discovery))
docker network create app-network
docker run -d \
--name db \
--network app-network \
-e MYSQL_ROOT_PASSWORD=pass \
mysql:8.0
docker run -d \
--name webapp \
--network app-network \
-p 8080:8080 \
-e DB_HOST=db \
-e DB_PORT=3306 \
myapp:latest이렇게 DNS 의 식별자로 --name 을 지정하고 있는 것을 볼 수 있다.
컨테이너 호스트명 설정
--hostname 옵션을 사용하여 컨테이너 내부에서 보이는 시스템 호스트명을 설정할 수 있다(bash 함수의 hostname 을 말함).
docker run -d \
--name webapp \
--hostname webapp.local \
--network my-bridge \
nginx
docker exec webapp hostname
# webapp.local 가 출력
docker exec webapp cat /etc/resolv.conf
# 하지만 DNS 는 다름
# webapp ??.??.??.??
docker-compose에서는 container_name 이 있으면container_name을 따르고, 없으면service_name을 따르게 된다.
보통 container_name 사용은 되도록 피하는게 좋다고 한다. compose 스케일링이 이름이 중복되어서 불가능하게 되고, 기본 네이밍 규칙이 깨져 관리가 어려우며, 네트워크 alias 자동 새엉 기능을 방해하기 때문이다. 따라서 서비스 이름 기반 DNS 를 사용하며 container_name 은 지정 안하는게 좋다.
포트 바인딩 vs EXPOSE
EXPOSE
FROM nginx
EXPOSE 80위는 실제로 포트가 열리는게 아니라 메타데이터로써 알리는 용도일 뿐이다.
포트바인딩
docker run -p 8080:80 nginx위는 실제로 호스트 컴퓨터의 8080 으로 들어온 것들을 도커 엔진 쪽의 80 번 포트로 포워딩 해주게 된다. 이때 컨테이너는 안에 80 번을 열어놔야 한다(nginx 는 기본적으로 80번이 열려있다).
Docker Network 명령어 정리
# 네트워크 생성
docker network create my-network
# 네트워크 조회
docker network ls
docker network inspect my-network
# 실행 중인 컨테이너를 네트워크에 연결/해제
docker network connect my-network container_name
docker network disconnect my-network container_name
# 네트워크 삭제
docker network rm my-network