ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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
Designed by Tistory.