-
[Docker] 자체 네트워크 드라이버Docker 2019. 4. 8. 00:02
도커 자체 네트워크 드라이버는 도커 엔진의 일부이기 때문에 추가 모듈이 필요하지 않다. 따라서 docker network 명령으로 바로 사용할 수 있다.
Docker Host Network Driver
일반적으로 다른 네트워킹 드라이버를 사용하면 각 컨테이너는 서로 간의 완전한 네트워크 분리를 위해 자체 네트워크 네임스페이스(혹은 샌드박스)에 배치된다. 호스트 네트워크 드라이버는 컨테이너가 호스트의 네트워킹 스택을 사용하는 옵션이다. 호스트 드라이버의 컨테이너는 모두 같은 호스트 네트워크에 있고, 호스트의 IP 스택과 네트워크 인터페이스를 사용할 수 있다. 호스트 네트워크의 모든 컨테이너들은 호스트 인터페이스에서 서로 통신할 수 있다.
네트워킹 관점에서 컨테이너가 없는 호스트에서 여러 프로세스가 동작하는것과 완전히 동일하다. 모든 컨테이너가 같은 호스트 인터페이스를 사용하기 때문에 두개의 컨테이너가 같은 TCP 포트에 바인딩할 수 없다.
아래 Dockerfile을 기반으로 이미지 빌드 한다. EXPOSE는 컨테이너가 실행되었을 때 해당 포트를 사용하는 옵션이다.
FROM centos RUN yum -y install httpd RUN echo 'Hello Devaom!' > /var/www/html/index.html CMD /usr/sbin/httpd -D FOREGROUND EXPOSE 80
--net=host 옵션으로 호스트 네트워크 드라이버를 사용하는 컨테이너를 생성한 후, 포트를 확인한다. 호스트 네트워크를 공유하기 때문에 호스트의 80포트가 자동으로 노출되었다.
$ docker run -itd --name centos-expose --net host centos:expose b25cbadce19a575def5bba6d5f7022730e81364d7819c40d8edcbd054eb2434b $ netstat -nltp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp6 0 0 :::80 :::* LISTEN 29622/httpd ...
호스트 네트워크를 사용하는 경우에는 아래와 같이 NetworkSettings.Networks에 host 필드가 생성된다.
$ docker inspect centos-expose ... "NetworkSettings": { "Bridge": "", "SandboxID": "37f2f07972d48b3ccf2522d599dc4d7444da008fd1279f136bf728677ed93837", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/default", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": { "host": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "cf5452a38e6b0b901e5faa491b8f8bdf8587db5e34d0d30f28a444e4e2f9c029", "EndpointID": "2ac1777633d89ca4a09e8c099e18e3377147b0fc25f8551e5b72037bdaa94370", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "", "DriverOpts": null } } } } ]
호스트 네트워크를 사용하는 컨테이너는 로컬호스트로 통신이 가능하다.
$ curl localhost Hello Devaom!
호스트 네트워크 모드에서 --mac-address 옵션은 유효하지 않으며, 심지어 컨테이너는 자체 UTS 네임스페이스를 기본적으로 가진다. 이와 같이 --hostname 옵션이 사용 가능하며 컨테이너 내부의 hostname만 변경된다. --hostname과 마찬가지로 --add-host, --dns, --dns-search 및 --dns-option 을 호스트 네트워크에서 사용할 수 있다. 이러한 옵션은 컨테이너 내부의 /etc/hosts 또는 /etc/resolv.conf를 업데이트한다. 컨테이너의 /etc/hosts, /etc/resolv.conf를 변경한다고 해서 호스트의 /etc/hosts, /etc/resolv.conf가 변경되지는 않는다.
Default Docker Bridge Network Driver
bridge는 네트워크 드라이버 혹은 템플릿이다. docker0는 bridge 네트워크 드라이버를 통해 인스턴스화되는 도커 기본 리눅스 브릿지이다.
도커 엔진을 실행하면 자동으로 docker0 리눅스 브릿지가 생성된다.
$ ip a s ... 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:1c:85:ff:f3 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:1cff:fe85:fff3/64 scope link valid_lft forever preferred_lft forever
docker run 명령은 별도 명시하지 않는 한 기본 브릿지 드라이버를 사용하여 컨테이너를 실행한다. 호스트에 생성된 veth582525a 인터페이스는 컨테이너 내부의 eth0 인터페이스로의 연결을 제공한다. 컨테이너 eth0 인터페이스의 MAC 주소는 동적으로 생성되고, IP주소는 자체 IPAM 드라이버에 의해 주소를 할당받는다.
$ docker run -itd --name busybox-bridge busybox 64504966f03549c54e033b76ff8d2d8d73ebdfb830ee0a6992d75c31f22f8d00 $ ip a s ... 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:1c:85:ff:f3 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever inet6 fe80::42:1cff:fe85:fff3/64 scope link valid_lft forever preferred_lft forever 56: veth582525a@if55: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether c6:bf:6c:76:97:ea brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::c4bf:6cff:fe76:97ea/64 scope link valid_lft forever preferred_lft forever $ docker exec busybox-bridge ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 55: eth0@if56: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever
brctl 도구로도 브릿지에 연결된 인터페이스들을 확인할 수 있다.
$ brctl show bridge name bridge id STP enabled interfaces docker0 8000.02421c85fff3 no veth582525a
컨테이너 내부의 라우팅 테이블은 트래픽을 eth0로 라우팅하고, 이어서 docker0 리눅스 브릿지로 유도된다. docker0 리눅스 브릿지는 172.17.0.0/16 네트워크를 사용하고, 기본 게이트웨이는 172.17.0.1 이다.
$ docker exec busybox-bridge ip route default via 172.17.0.1 dev eth0 172.17.0.0/16 dev eth0 scope link src 172.17.0.2
NAT 테이블을 확인해보면, 마스커레이딩 설정되어 있는 것을 확인할 수 있다.
$ iptables -L -t nat Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere !loopback/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- ip-172-17-0-0.ap-northeast-2.compute.internal/16 anywhere Chain DOCKER (2 references) target prot opt source destination RETURN all -- anywhere anywhere
기본 브릿지 네트워크를 사용하여 생성한 컨테이너에는 NetworkSettings.Networks에 bridge 필드가 생성된다.
$ docker inspect busybox-bridge ... "NetworkSettings": { "Bridge": "", "SandboxID": "99e39b3fddaae6e85d758da4af389e59be2cf480ee42171f0969951a5e2d094d", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/99e39b3fddaa", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "7acd0bad8f0c649944a4823ac35c84e644a75d904e8d3a8a1f408afaeb48f04c", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "8d11980cfddb000e9c17947cd81208c8a8585a4d80eff25ca911b3ad73ebc67c", "EndpointID": "7acd0bad8f0c649944a4823ac35c84e644a75d904e8d3a8a1f408afaeb48f04c", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null } } } } ]
User-defined Docker Bridge Network Driver
기본 브릿지 네트워크 외에도 사용자 정의 네트워크라는 자체 네트워크를 생성할 수 있다. 사용자 정의 브릿지 네트워크의 경우, 새로운 리눅스 브릿지가 호스트에 설정된다.
기본 브릿지 네트워크와는 달리 사용자 정의 네트워크는 수동 IP 주소와 서브넷 할당을 지원한다. 도커의 기본 IPAM 드라이버는 프라이빗 IP 공간에 사용할 수 있는 서브넷을 할당한다.
사용자 정의 브릿지 네트워크를 생성한다. 게이트웨이는 --gateway 옵션을 주면 된다.
$ docker network create -d bridge --subnet 10.0.0.0/8 bridge-cust e03c1a7509f5348cb8925dbd8b452d6d5aa4107faee1157c352c38bed212f0d0 $ docker network ls NETWORK ID NAME DRIVER SCOPE 8d11980cfddb bridge bridge local e03c1a7509f5 bridge-cust bridge local cf5452a38e6b host host local 0857dc77ddb1 none null local $ docker inspect bridge-cust [ { ... "Driver": "bridge", "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "10.0.0.0/8" } ] }, ... $ iptables -L -t nat Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere anywhere ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- anywhere !loopback/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- ip-10-0-0-0.ap-northeast-2.compute.internal/8 anywhere MASQUERADE all -- ip-172-17-0-0.ap-northeast-2.compute.internal/16 anywhere Chain DOCKER (2 references) target prot opt source destination RETURN all -- anywhere anywhere RETURN all -- anywhere anywhere
bridge-cust 브릿지 네트워크의 br-e03c1a7509f5 리눅스 브릿지가 생성되었다.
$ ip a s ... 58: br-e03c1a7509f5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:40:ac:ba:49 brd ff:ff:ff:ff:ff:ff inet 10.0.0.1/8 brd 10.255.255.255 scope global br-e03c1a7509f5 valid_lft forever preferred_lft forever inet6 fe80::42:40ff:feac:ba49/64 scope link valid_lft forever preferred_lft forever
bridge-cust 브릿지 네트워크에 컨테이너를 신규로 생성한다. bridge-cust 네트워크의 IP 주소가 할당되었다.
$ docker run -itd --name busybox-bridge-cust --net bridge-cust busybox a801c1423c41e79bdfe5a233357be17cece444b241415ed8f0101ce424e4a7b3 $ docker exec busybox-bridge-cust ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff inet 10.0.0.2/8 brd 10.255.255.255 scope global eth0 valid_lft forever preferred_lft forever
None(Isolated) Network
none 네트워크 드라이버를 사용하여 컨테이너를 생성하면, 도커 엔진은 컨테이너 내부에 인터페이스 생성, 포트 매핑 설정, 라우팅 설정을 하지 않는다. 따라서 완전히 다른 컨테이너와 호스트로부터 격리된다. 컨테이너는 오직 루프백 인터페이스만 가진다.
$ docker run -itd --name busybox-none --net none busybox aabff1ace6d615c3c2aad903515b9f9a7e0c08ee14bec225fe9957e037eb6f8e $ docker exec busybox-none ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever
none 네트워크 옵션으로 생성된 컨테이너는 모든 들어오고 나가는 트래픽은 비활성화되며, 오직 STDIN, STDOUT으로만 I/O를 수행할 수 있다.
'Docker' 카테고리의 다른 글
[Docker] Dockerfile (1) 2019.04.04 [Docker] 데이터 볼륨 (0) 2019.04.03 [Docker] 이미지 아카이브 (1) 2019.04.02 [Docker] 컨테이너의 구조 (1) 2019.04.02