1. 도커 네트워크 구조
도커는 컨테이너에 내부 IP(172.17.0.)를 순차적으로 할당하며, 이 IP는 컨테이너가 restart될 때 마다 변경될 수 있습니다.
이 IP는 도커가 설치된 호스트, 즉 내부망에서만 쓸 수 있는 IP이므로 외부와 연결될 필요가 있습니다.
도커가 설치된 호스트에서 ifconfig 나 ip addr과 같은 명령어로 네트워크 인터페이스르르 확인하면 실행 중인 컨테이너 수 만큼 veth~(virtual ethernet) 로 시작되는 인터페이스를 확인할 수 있습니다.
vethf7119a1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::e8f2:50ff:fe9a:ee4f prefixlen 64 scopeid 0x20<link>
ether ea:f2:50:9a:ee:4f txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6 bytes 516 (516.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
veth 인터페이스 뿐 아니라 docker0 이라는 브릿지도 존재하는데 이는 각 veth 인터페이스와 바인딩돼 호스트의 eth0 인터페이스와 이어주는 역할을 합니다.
컨테이너의 eth0 -> veth -> docker0(bridge) -> 호스트의 eth0
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e2b89ac3ca3f mysql:5.7 "docker-entrypoint.s…" 2 seconds ago Up 1 second 3306/tcp, 33060/tcp wordpressDB
a79dcb5e83a4 ubuntu:18.04 "/bin/bash" 6 minutes ago Up 5 minutes 192.168.1.166:7777->80/tcp, 0.0.0.0:33006->3306/tcp, :::33006->3306/tcp busy_bhabha
[root@localhost ~]# brctl show docker0
bridge name bridge id STP enabled interfaces
docker0 8000.0242867c6d4a no vethd5630bd
vethf7119a1
brctl 명령을 이용해 docker0 브릿지에 veth이 바인딩 됐는지 알 수 있습니다.
*yum install bridge-utils 로 brctl 명령 사용가능
2. 도커 네트워크 기능
컨테이너를 생성하면 기본적으로 docker0 브릿지를 통해 외부와 통신할 수 있는 환경을 사용할 수 있지만 선택에 따라 여러 네트워크 드라이버를 쓸 수 있습니다.
[대표적인 네트워크 드라이버 : 브릿지(bridge), 호스트(host), 논(none), 컨테이너(container), 오버레이(overlay)]
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a0fe76a9a6f2 bridge bridge local
06090926962c host host local
75f18a671367 none null local
도커에서 기본적으로 쓸 수 있는 네트워크는 위와 같습니다.
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "a0fe76a9a6f221321b15d943de58aabd42465225b8a0538db7653f762df252e5",
"Created": "2021-05-24T09:24:37.100341624+09:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
...
config 항목의 서브넷과 게이트웨이가 172.17.0.0/16 과 172.17.0.1 로 설정돼 있습니다.
아무런 설정을 하지 않고 컨테이너를 생성하면 자동으로 docekr0 브릿지를 사용합니다.
● 브릿지 네트워크
[root@localhost ~]# docker network create --driver bridge mybridge
cf451fe3c6d74a422063d4853c357a96a5dce3b02d4c3780e6cf7962f40c5c4c
기본적으로 존재하는 docker0 브릿지가 아닌 새로운 브릿지 타입의 네트워크를 생성했습니다.
[root@localhost ~]# docker run -i -t mybridge_container --net mybridge ubuntu:18.04
apt update 및 apt install net-tools
root@2b4ec8fb7582:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.19.0.2 netmask 255.255.0.0 broadcast 172.19.255.255
ether 02:42:ac:13:00:02 txqueuelen 0 (Ethernet)
RX packets 10933 bytes 23585887 (23.5 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7614 bytes 608909 (608.9 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 6 bytes 818 (818.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6 bytes 818 (818.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
172.19.0 의 IP 대역을 할당받은 것을 확인할 수 있습니다.
br-cf451fe3c6d7: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.19.0.1 netmask 255.255.0.0 broadcast 172.19.255.255
inet6 fe80::42:aeff:feb8:145f prefixlen 64 scopeid 0x20<link>
ether 02:42:ae:b8:14:5f txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 656 (656.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
도커의 호스트에서 위와 같은 네트워크 인터페이스가 생성된 것을 확인할 수 있습니다.
이렇게 생성된 사용자 정의 네트워크는 docker netowrk disconnect, connect 를 통해 컨테이너에 유동적으로 붙이고 뗄 수 있습니다.
docker network disconnect mybridge mynetwork_container
docker network connect mybridge mynetwork_container
네트워크의 서브넷, 게이트웨이, IP 할당 범위등을 임의로 설정하려면 네트워크 생성 시 아래와 같이 옵션을 추가합니다.
docker network create --driver=bridge --subnet=172.72.0.0/16 --ip-range=172.72.0.0/24 --gateway=172.72.0.1 my_custom_network
● 호스트 네트워크
네트워크를 호스트로 설정하면 호스트의 네트워크 환경을 그대로 쓸 수 있습니다.
브릿지 드라이버 네트워크와는 달리 호스트 드라이버 네트워크는 별도로 생성할 필요 없이 기존 host라는 이름의 네트워크를 사용합니다.
[root@localhost ~]# docker run -t -i --name network_host --net host ubuntu:18.04
root@localhost:/#
host 라는 network 를 사용하는 컨테이너를 생성하였으며 호스트이름도 무작위 16진수가 아닌 도커가 설치된 호스트 머신의 호스트 이름으로 설정됩니다.
호스트 네트워크를 쓰는 컨테이너에서 서비스를 구동한다면 IP와 port의 바인딩 없이 바로 접근 가능합니다.
● 논(none) 네트워크
말 그대로 아무런 네트워크를 쓰지 않는 것을 뜻합니다.
[root@localhost ~]# docker run -t -i --name network_none --net none ubuntu:18.04
--net 옵션으로 none을 설정한 컨테이너의 네트워크는 로컬호스트를 나타내는 lo 인터페이스 밖에 존재하지 않습니다.
즉 외부와의 연결이 단절됩니다.
● 컨테이너 네트워크
다른 컨테이너의 네트워크 네임스페이스 환경을 공유할 수 있습니다.
[root@localhost ~]# docker run -t -i -d --name network_container_1 ubuntu:18.04
33631d482512d2a6da26283184fd5e8e39680f3a02e3dcca184580183c4e0087
[root@localhost ~]#
[root@localhost ~]#
[root@localhost ~]# docker run -t -i -d --name network_container_2 --net container:network_container_1 ubuntu:18.04
cb8e6a6a989de3cd5828028bfa8bee586f0f940065a91ff0f7244ddca9cb7fb1
[root@localhost ~]#
두 컨테이너의 eth0에 대한 정보는 완전히 같습니다.
즉 container_1 과 container_2가 같은 eth0 이며 같은 veth를 가져 docker0 로 연결되는 구조입니다.
● 브릿지 네트워크와 --net-alias
--net-alias 옵션에 설정된 특정 호스트 이름으로 컨테이너 여러 개에 접근할 수 있습니다.
[root@localhost ~]# docker run -t -i -d --name network_container_1 --net mybridge --net-alias sotest ubuntu:18.04
78bfcb3aef4ec1623a3c74e14f96648e92a575b4faa0f96f0a848db67ea01ef7
[root@localhost ~]# docker run -t -i -d --name network_container_2 --net mybridge --net-alias sotest ubuntu:18.04
ecafcb061aa4ff573f50bbbbee1e1e829976c2fc84bbbeea53bdd8a93e3d2f82
[root@localhost ~]# docker run -t -i -d --name network_container_3 --net mybridge --net-alias sotest ubuntu:18.04
719c686c7e6670391489bb9572f25615620390935cbdea8f9c4f710cfea7ea08
[root@localhost ~]# docker run -t -i --name pingtest --net mybridge ubuntu:18.04
97063551c7cfc88f9358842af705045b5b4cf39faaf1ddbee560ecf4d271c00d
--net-alias sotest 옵션이 설정된 컨테이너 3개를 생성했으며 같은 브릿지 네트워크로 핑테스트 할 컨테이너 하나를 생성했습니다.
pingtest 라는 컨테이너에 진입하여 sotest 라는 호스트이름으로 ping 명령을 해보면 다음과 같습니다.
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.188/0.188/0.188/0.000 ms
root@97063551c7cf:/# ping sotest -c 1
PING sotest (172.19.0.3) 56(84) bytes of data.
64 bytes from network_container_2.mybridge (172.19.0.3): icmp_seq=1 ttl=64 time=0.163 ms
--- sotest ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.163/0.163/0.163/0.000 ms
root@97063551c7cf:/# ping sotest -c 1
PING sotest (172.19.0.2) 56(84) bytes of data.
64 bytes from network_container_1.mybridge (172.19.0.2): icmp_seq=1 ttl=64 time=0.106 ms
--- sotest ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.106/0.106/0.106/0.000 ms
root@97063551c7cf:/# ping sotest -c 1
PING sotest (172.19.0.2) 56(84) bytes of data.
64 bytes from network_container_1.mybridge (172.19.0.2): icmp_seq=1 ttl=64 time=0.098 ms
--- sotest ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.098/0.098/0.098/0.000 ms
root@97063551c7cf:/# ping sotest -c 1
PING sotest (172.19.0.4) 56(84) bytes of data.
64 bytes from network_container_3.mybridge (172.19.0.4): icmp_seq=1 ttl=64 time=0.163 ms
컨테이너 3개의 IP로 각각 ping이 전송된 것을 확인할 수 있습니다.
매번 달라지는 IP를 결정하는 것은 라운드 로빈 방식으로 진행됩니다.
도커엔진에 내장된 DNS가 해당 호스트 이름을 sotest로 설정한 컨테이너로 변환하기 때문입니다.
도커의 DNS는 호스트 이름으로 유동적인 컨테이너를 찾을 때 주로 사용됩니다.
이는 컨테이너의 IP가 변경돼도 별명으로 컨테이너를 찾을 수 있게 DNS에 의해 관리됩니다.
root@97063551c7cf:/# dig sotest
; <<>> DiG 9.11.3-1ubuntu1.15-Ubuntu <<>> sotest
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26398
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;sotest. IN A
;; ANSWER SECTION:
sotest. 600 IN A 172.19.0.3
sotest. 600 IN A 172.19.0.4
sotest. 600 IN A 172.19.0.2
;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Mon May 24 05:57:38 UTC 2021
;; MSG SIZE rcvd: 90
위 명령으로 sotest 호스트 이름이 변환되는 IP를 확인할 수 있습니다.
명령을 반복해서 입력해보면 반환되는 IP의 리스트 순서가 계속적으로 바뀌는 것을 확인할 수 있습니다.
● MacVLAN 네트워크
개념이 어려우므로 다음에 이부분만 따로 포스팅,,
'docker' 카테고리의 다른 글
도커 컨테이너 다루기(6) - 컨테이너 자원 할당 제한 (1) | 2021.05.29 |
---|---|
도커 컨테이너 다루기(5) - 컨테이너 로깅 (0) | 2021.05.28 |
도커 컨테이너 다루기(3) - 도커 볼륨 (0) | 2021.05.25 |
도커 컨테이너 다루기(2) - 컨테이너 외부 노출 (0) | 2021.05.24 |
도커 컨테이너 다루기(1) - 생성/진입/삭제 (0) | 2021.04.19 |