1. 개요
Docker의 주요 기능 중 하나는 네트워크 생성 및 격리입니다.
이 예제에서는 네트워크와 네트워크가 보유하고 있는 컨테이너에 대한 정보를 추출하는 방법을 알아봅니다.
2. 도커의 네트워킹
Docker 컨테이너를 실행할 때 외부 세계에 노출하려는 포트를 정의할 수 있습니다. 이것이 의미하는 바는 우리가 격리된 네트워크를 사용(또는 생성)하고 컨테이너를 안에 넣는다는 것입니다. 우리는 이 네트워크와 통신하는 방법을 결정할 수 있습니다.
몇 개의 컨테이너를 만들고 이들 간의 네트워킹을 구성해 보겠습니다. 모두 내부적으로 포트 8080에서 작동하며 두 개의 네트워크에 배치됩니다.
각각은 간단한 "Hello World" HTTP 서비스를 호스팅합니다.
version: "3.5"
services:
test1:
image: node
command: node -e "const http = require('http'); http.createServer((req, res) => { res.write('Hello from test1\n'); res.end() }).listen(8080)"
ports:
- "8080:8080"
networks:
- network1
test2:
image: node
command: node -e "const http = require('http'); http.createServer((req, res) => { res.write('Hello from test2\n'); res.end() }).listen(8080)"
ports:
- "8081:8080"
networks:
- network1
- network2
test3:
image: node
command: node -e "const http = require('http'); http.createServer((req, res) => { res.write('Hello from test3\n'); res.end() }).listen(8080)"
ports:
- "8082:8080"
networks:
- network2
networks:
network1:
name: network1
network2:
name: network2
다음은 보다 시각적인 표현을 위한 이러한 컨테이너의 다이어그램입니다.
docker-compose 명령으로 모두 시작하겠습니다 .
$ docker-compose up -d
Starting bael_test2_1 ... done
Starting bael_test3_1 ... done
Starting bael_test1_1 ... done
3. 네트워크 검사
먼저 사용 가능한 모든 Docker 네트워크를 나열해 보겠습니다.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
86e6a8138c0d bridge bridge local
73402de5766c host host local
e943f7124776 network1 bridge local
3b9a28673a16 network2 bridge local
9361d16a834a none null local
docker run 명령을 사용할 때 사용되는 기본 네트워크인 브리지 네트워크를 볼 수 있습니다 . 또한 docker-compose 명령으로 생성한 네트워크를 볼 수 있습니다 .
docker inspect 명령으로 검사해 보겠습니다 .
$ docker inspect network1 network2
[
{
"Name": "network1",
"Id": "e943f7124776d45a1481ee26795b2dba3f2ab51f000d875a179a99ce832eee9f",
"Created": "2020-08-22T10:38:22.198709146Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
// output cutout for brevity
}
],
{
"Name": "network2",
// output cutout for brevity
}
}
이렇게 하면 길고 자세한 출력이 생성됩니다. 이 모든 정보가 필요한 경우는 거의 없습니다. 다행히 Go 템플릿을 사용하여 형식을 지정 하고 필요에 맞는 요소만 추출 할 수 있습니다 . network1 의 서브넷만 가져오겠습니다 .
$ docker inspect -f '{{range .IPAM.Config}}{{.Subnet}}{{end}}' network1
172.22.0.0/16
4. 용기 검사
마찬가지로 특정 컨테이너를 검사할 수 있습니다. 먼저 식별자가 있는 모든 컨테이너를 나열해 보겠습니다.
$ docker ps --format 'table {{.ID}}\t{{.Names}}'
CONTAINER ID NAMES
78c10f03ad89 bael_test2_1
f229dde68f3b bael_test3_1
b09a8f47e2a8 bael_test1_1
이제 컨테이너의 ID를 inspect 명령에 대한 인수로 사용하여 IP 주소를 찾습니다. 네트워크와 유사하게, 우리는 우리가 필요한 정보를 얻기 위해 출력을 포맷할 수 있습니다. 생성한 두 네트워크에서 두 번째 컨테이너와 해당 주소를 확인합니다.
$ docker inspect 78c10f03ad89 --format '{{.NetworkSettings.Networks.network1.IPAddress}}'
172.22.0.2
$ docker inspect 78c10f03ad89 --format '{{.NetworkSettings.Networks.network2.IPAddress}}'
172.23.0.3
또는 docker exec 명령을 사용하여 컨테이너에서 직접 호스트를 인쇄할 수 있습니다 .
$ docker exec 78c10f03ad89 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.22.0.2 78c10f03ad89
172.23.0.3 78c10f03ad89
5. 컨테이너 간 통신
Docker 네트워크에 대한 지식을 사용하여 동일한 네트워크의 컨테이너 간에 통신을 설정할 수 있습니다.
먼저 "test1" 컨테이너 내부로 들어가 보겠습니다.
$ docker exec -it b09a8f47e2a8 /bin/bash
그런 다음 curl을 사용하여 "test2" 컨테이너에 요청을 보냅니다.
root@b09a8f47e2a8:/# curl 172.22.0.2:8080
Hello from test2
Docker 네트워크 내부에 있으므로 IP 주소 대신 별칭을 사용할 수도 있습니다. Docker의 내장 DNS 서비스가 주소를 확인합니다.
root@b09a8f47e2a8:/# curl test2:8080
Hello from test2
다른 네트워크에 있기 때문에 "test3" 컨테이너에 연결할 수 없습니다. IP 주소로 연결하면 시간이 초과됩니다.
root@b09a8f47e2a8:/# curl 172.23.0.2:8080
DNS 서비스가 이를 인식하지 못하기 때문에 별칭으로 연결하는 것도 실패합니다.
root@b09a8f47e2a8:/# curl test3:8080
curl: (6) Could not resolve host: test3
이 작업을 수행하려면 "test3" 컨테이너를 "network1"(컨테이너 외부에서)에 추가해야 합니다.
$ docker network connect --alias test3 network1 f229dde68f3b
이제 "test3"에 대한 요청이 올바르게 작동합니다.
root@b09a8f47e2a8:/# curl test3:8080
Hello from test3
6. 결론
이 사용방법(예제)에서는 Docker 컨테이너에 대한 네트워크를 구성한 다음 이에 대한 정보를 쿼리하는 방법을 살펴보았습니다.