Docker 컨테이너(container)는 격리된 환경에서 돌아가기 때문에 기본적으로 다른 컨테이너와의 통신이 불가능합니다. 하지만 여러 개의 컨테이너를 하나의 Docker 네트워크(network)에 연결시키면 서로 통신이 가능해집니다. 이번 포스팅에서는 컨테이너 간 네트워킹이 가능하도록 도와주는 Docker 네트워크에 대해서 알아보도록 하겠습니다.
네트워크 조회
docker network ls 명령어를 사용하면 현재 생성되어 있는 Docker 네트워크 목록을 조회합니다.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
26269a11d9ca bridge bridge local
187a5a20afaa engn001_network bridge local
ddbf38931eb2 host host local
e2861fc3c87a none null local
bridge, host, none은 Docker 데몬(daemon)이 실행되면서 디폴트로 생성되는 네트워크입니다. 디폴트 네트워크를 이용하는 것 보다는 사용자가 직접 네트워크를 생성해서 사용하는 것이 권장됩니다.(예시, engn001_network)
네트워크 종류
Docker 네트워크는 bridge, host, overlay 등 목적에 따라 다양한 종류의 네트워크 드라이버(driver)를 지원합니다.
- bridge 네트워크는 하나의 호스트 컴퓨터 내에서 여러 컨테이너들이 서로 소통할 수 있도록 해줍니다.
- host 네트워크는 컨터이너를 호스트 컴퓨터와 동일한 네트워크에서 컨테이너를 돌리기 위해서 사용됩니다.
- overlay 네트워크는 여러 호스트에 분산되어 돌아가는 컨테이너들 간에 네트워킹을 위해서 사용됩니다.
본 문서에서는 기본값이고 가장 많이 사용되는 bridge 네트워크에 대해서만 다루도록 하겠습니다.
네트워크 생성
먼저 docker network create 커맨드를 사용해서 새로운 Docker 네트워크를 생성해 봅니다.
$ docker network create our-net
e6dfe4a9a5ec85abcb484662c30a3a0fc76df217dde76d52fac39fae8412ca68
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
143496b94e57 bridge bridge local
311d6534f79f host host local
aa89f58200a6 none null local
e6dfe4a9a5ec our-net bridge local
네트워크 상세 정보
방금 추가한 네트워크의 상세 정보를 docker network inspect 커맨드로 확인해보도록 하겠습니다.
$ docker network inspect our-net
[
{
"Name": "our-net",
"Id": "e6dfe4a9a5ec85abcb484662c30a3a0fc76df217dde76d52fac39fae8412ca68",
"Created": "2020-04-26T19:23:04.563643516Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
네트워크에 컨테이너 연결
먼저 컨테이너 하나를 one라는 이름으로 실행해보도록 하겠습니다.
$ docker run -itd --name one busybox
660bafdce2996378cde070dfd894731bb90745e46d2ab10d6504c0cc9f4bdea9
컨테이너를 실행할 때 --network 옵션을 명시해주지 않으면, 기본적으로 bridge라는 이름의 디폴트 네트워크에 붙게 됩니다.
$ docker network inspect bridge
(... 생략 ...)
"Containers": {
"660bafdce2996378cde070dfd894731bb90745e46d2ab10d6504c0cc9f4bdea9": {
"Name": "one",
"EndpointID": "40b4bbd8385debf86eef2fc2136315e1a82fa1ef72877bfae25477d6e8e46726",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
},
(... 생략 ...)
이 one 컨테이너를 위에서 생성한 our-net 네트워크에 연결해보도록 하겠습니다. Docker 네트워크에 컨테이너를 연결할 때는 docker network connect 커맨드를 사용합니다.
$ docker network connect our-net one
our-net 네트워크의 상세 정보를 다시 확인해보면 Containers 항목에 one 컨테이너가 추가된 것을 볼 수 있습니다. one 컨테이너에 IP 172.19.0.2가 할당된 것도 확인할 수 있습니다.
$ docker network inspect our-net
[
{
"Name": "our-net",
"Id": "e6dfe4a9a5ec85abcb484662c30a3a0fc76df217dde76d52fac39fae8412ca68",
"Created": "2020-04-26T19:23:04.563643516Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"660bafdce2996378cde070dfd894731bb90745e46d2ab10d6504c0cc9f4bdea9": {
"Name": "one",
"EndpointID": "cc490148a533d40b3aff33a421cc9a01c731c75a8deb70ab729a5358f2fd381c",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
네트워크로부터 컨테이너 연결 해제
하나의 컨테이너는 여러 개의 네트워크에 동시에 연결할 수 있습니다. 최초에 one 컨테이너를 생성할 때 bridge 네트워크 붙었기 때문에, 현재 one 컨테이너는 our-net 네트워크와 bridge 네트워크에 동시에 붙어있게 됩니다.
one 컨테이너를 bridge 네트워크로부터 때어 내도록 하겠습니다. Docker 네트워크로부터 컨테이너의 연결을 끊을 때는 docker network disconnect 커맨드를 사용합니다.
$ docker network disconnect bridge one
두번째 컨테이너 연결
하나의 컨테이너를 더 our-net 네트워크에 연결해 봅니다.
이번에는 --network 옵션을 사용해서 컨테이너를 실행하면서 바로 연결할 네트워크를 지정해주도록 하겠습니다.
$ docker run -itd --name two --network our-net busybox
0e7fe8a59f9d3f8bd545d3e557ffd34100a09b8ebe92ae5a375f37a5d072873d
our-net 네트워크의 상세 정보를 확인해보면 two 컨테이너에 IP 172.19.0.3가 할당되어 연결되어 있는 것을 확인할 수 있습니다.
$ docker network inspect our-net
[
{
"Name": "our-net",
"Id": "e6dfe4a9a5ec85abcb484662c30a3a0fc76df217dde76d52fac39fae8412ca68",
"Created": "2020-04-26T19:23:04.563643516Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0e7fe8a59f9d3f8bd545d3e557ffd34100a09b8ebe92ae5a375f37a5d072873d": {
"Name": "two",
"EndpointID": "a0e3625e48f0b833cd551d6dfb3b1a2a7614f1343adbc5e6aefa860d917ddea9",
"MacAddress": "02:42:ac:13:00:03",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": ""
},
"660bafdce2996378cde070dfd894731bb90745e46d2ab10d6504c0cc9f4bdea9": {
"Name": "one",
"EndpointID": "cc490148a533d40b3aff33a421cc9a01c731c75a8deb70ab729a5358f2fd381c",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
컨테이너 간 네트워킹
이제 두 개의 컨테이너가 네트워크를 통해 서로 소통이 가능한지 테스트를 해보도록 하겠습니다.
먼저 one 컨테이너에서 two 컨테이너를 상대로 ping 명령어를 날려보겠습니다. 컨테이너 이름을 호스트네임(hostname)처럼 사용할 수 있습니다.
$ docker exec one ping two
PING two (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.119 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.105 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.116 ms
64 bytes from 172.19.0.3: seq=3 ttl=64 time=0.883 ms
64 bytes from 172.19.0.3: seq=4 ttl=64 time=0.127 ms
반대로 two 컨테이너에서 one 컨테이너를 상대로 ping 명령어를 날려보겠습니다. 이번에는 컨테이너 이름 대신에 IP를 사용하겠습니다.
$ docker exec two ping 172.19.0.2
PING 172.19.0.2 (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.927 ms
64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.079 ms
64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.080 ms
64 bytes from 172.19.0.2: seq=3 ttl=64 time=0.079 ms
64 bytes from 172.19.0.2: seq=4 ttl=64 time=0.107 ms
네트워크 제거
마지막으로 docker network rm 커맨드를 사용해서 our-net 네트워크를 제거해보겠습니다.
$ docker network rm our-net
Error response from daemon: error while removing network: network our-net id e6dfe4a9a5ec85abcb484662c30a3a0fc76df217dde76d52fac39fae8412ca68 has active endpoints
위와 같이 제거하려는 네트워크 상에서 실행 중인 컨테이너가 있을 때는 제거가 되지가 않습니다.
그럴 때는 해당 네트워크에 연결되어 실행 중인 모든 컨테이너를 먼저 중지 시키고, 네트워크를 삭제해야 합니다.
$ docker stop one two
one
two
$ docker network rm our-net
our-net
네트워크 정리
하나의 호스트 컴퓨터에서 다수의 컨테이너를 돌리다 보면 아무 컨테이너도 연결되어 있지 않은 네트워크가 존재할 수 있습니다. 이럴 때는 docker network prune 커맨드를 이용해서 불필요한 네트워크를 한번에 모두 제거할 수 있습니다.
$ docker network prune
WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N] y
원문 : https://www.daleseo.com/docker-networks/
[ 참고 ]
Docker는 독립 된 네트워크를 구성 하기위하여 3가지 기술을 사용 합니다.
1) network namespace
- contianer안의 NIC와 Container의 NIC와 pair 되는 VNIC를 만드는데 사용 합니다.
* 자세한 설명(실습가능) : https://www.joinc.co.kr/w/man/12/NetworkNamespace#toc
2) bridge
- llinux에서 software로 구현 한 bridge
- bridge하나 당 개별 네트워크를 구성 할 수 있습니다.
- container에 bridge를 2개 할 당하면 Container는 2개의 NIC를 가질 수 있습니다.
- L2 통신만을 지원 합니다.
3) iptables
- Container가 외부 네트워크 통신을 하기 위해서 사용 됩니다.
- NAPT를 이용하여 통신을 한다.
*NAPT 란 ?
- 내부 사설 IP와 Port를 공용 IP와 Port로 변경 시켜주는 기능입니다. NAPT는 Network Address Port Translation의 약자로, NAT에서는 발신자의 사설망-외부망 IP를 바꿔서 보내주는 역할만을 수행했다면 이제는 포트까지 바꿔서 보내는 역할을 합니다. NAPT의 테이블은 NAT의 테이블에서 Port에 해당하는 컬럼이 추가됩니다.
- 네트워크 대역 지정
(1) 사용자 정의 네트워크를 생성시 IP 대역을 지정할 수 있습니다.
#docker network create
--driver=bridge \
--subnet=172.1.0.0/16 \
--ip-range=172.1.0.0/24 \
--gateway=172.1.0.1 \
mybridge
- Container IP 설정
(1) container 생성시 설정
#docker run -itd --ip 172.1.0.5 --net=mybridge --name=centos-network-1 centos
--ip : container에 할당 할 IP 설정
--net : container 할당 할 IP가 속해 있는 network 대역을 가진 bridge 설정
'Docker' 카테고리의 다른 글
도커 - web was 구성 (0) | 2022.04.21 |
---|---|
Docker Compose 네트워크 (0) | 2022.04.21 |
Docker - 파일 저장 위치 (0) | 2022.04.19 |
Install Docker Engine on CentOS (0) | 2022.04.18 |
Run the Docker daemon as a non-root user (Rootless mode) (0) | 2022.04.18 |