2,201 瀏覽數

Docker – network

測試環境為 Ubuntu16.04 ,關於 Docker 使用與設定請參考 http://benjr.tw/95998,這邊討論關於 Docker 網路的設定.

安裝完 Docker.io 之後觀察一下網路裝置的改變.可以看到多了一個 docker0 這個網路裝置.

Linux 網路提供 Bridge mode 他可以模擬一個 switch (Bridge) 來使用了,Container 的網卡就是單純透過虛擬的 switch 與其他 Containers 端的網卡相聯接.還提供 DHCP Server 的服務.

root@ubuntu:~# ifconfig docker
docker0   Link encap:Ethernet  HWaddr 02:42:68:0a:27:d6  
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

透過 brctl 可以查看這 docker0 的 bridge name , Bridge id ,STP (Spanning Tree Protocol) enabled 狀態, 以及哪一些 Container 是透過這個 Bridge 的 interfaces (這個 Bridge 未對應到實際上的網路卡裝置上).

root@ubuntu:~# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242680a27d6	no

下面的圖示你可以很清楚的看出來虛擬 NIC 是如何透過 bridge 模式串接在一起.

但 Docker 提供的網路模式不只有 Bridge 還有 Host , None 兩種,可以透過 docker 提供的指令來看看.

root@ubuntu:~# docker network --help

Usage:	docker network COMMAND

Manage Docker networks

Options:
      --help   Print usage

Commands:
  connect     Connect a container to a network
  create      Create a network
  disconnect  Disconnect a container from a network
  inspect     Display detailed information on one or more networks
  ls          List networks
  rm          Remove one or more networks
root@ubuntu:~# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
42510ee7d4f5        bridge              bridge              local               
1244579a7506        host                host                local               
3374f7af4b41        none                null                local  

Bridge

先來看看預設的 Bridge 的設定.與其他模式不同之處 Bridge 有定義 IPAM (IP address management),可以指派 IP(172.17.0.0/16) 給 Container 使用.功能同 DHCP .

root@ubuntu:~# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "42510ee7d4f52ce0b6b624f5aeed1a3ccc50f3bbc21b854d6b85209d8364bf85",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16"
                }
            ]
        },
        "Internal": false,
        "Containers": {},
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

目前沒有 Container 在運作,如果有可以在這邊觀察 Container IP .

開了一個 Container ,可以觀察 Container 網卡 veth747f1b9 是掛載在這裡.

root@ubuntu:~# docker run -t -i ubuntu:12.04 /bin/bash
Unable to find image 'ubuntu:12.04' locally
12.04: Pulling from library/ubuntu
7d172a1d710c: Pull complete 
0d35f4bc65ee: Pull complete 
19231e74a42a: Pull complete 
51880de525fb: Pull complete 
46b3aaaab3ec: Pull complete 
Digest: sha256:47effe29d7bed549fee8c63bd60120fa88785e72abfb2aeeccdda21f4eae67e4
Status: Downloaded newer image for ubuntu:12.04
root@9de75a7e1787:/#
root@ubuntu:~# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242c63b76cc	no		veth747f1b9
root@ubuntu:~# ifconfig veth747f1b9
veth747f1b9 Link encap:Ethernet  HWaddr f2:c4:97:61:23:90  
          inet6 addr: fe80::f0c4:97ff:fe61:2390/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:56 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:648 (648.0 B)  TX bytes:7160 (7.1 KB)

現在透過 Docker 指令來觀察會發現多了這個 Container 的網路的確有被指派到 IP 資料 172.17.0.2 .

root@ubuntu:~# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "033577a37a897889812ba71b3899e37c151eb90c5e2f410c4f55d9c78cfab1d9",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Containers": {
            "9de75a7e1787ce76aa32b942f765ee0516387eecc54e6f797b9d3554c0134979": {
                "Name": "berserk_ramanujan",
                "EndpointID": "acbc762a651244b1f8f76f0385859f6b00bf3f74b89c3d4f8d0e0e4ea7ff1916",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

Host

Container 預設為 Bridge 模式,如果要使用 Host 模式需要在建立 Container 時透過 –network=host 來指定.

root@ubuntu:~# docker run --name ubuntu-host --network=host -t -i ubuntu:12.04 /bin/bash

這時不管是透過 #ifconfig 或是 #brctl show 都沒有變化.因為這裡的模式與 Bridge 不一樣,Host 沒有建立一個 Container 與 Host 隔離的網路空間, Container 裡就可以看到在 Docker Host 所有的網路裝置.

這時的 Host 模式下 Docker 與 host 主機共享同一個 network namespace,那什麼是 namespace ?

namespace 命名空間是 Linux 內核的一個功能,他可以隔離和虛擬化 processes 相關系統資源,虛擬化資源包括 process IDs, hostnames, user IDs, network access, interprocess communication, 以及 filesystems .

在 Container 裡面看看,會觀察到與 Host 一樣的網路裝置.

root@ubuntu:/# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:27:a6:7f brd ff:ff:ff:ff:ff:ff
    inet 172.16.15.130/24 brd 172.16.15.255 scope global dynamic ens33
       valid_lft 940sec preferred_lft 940sec
    inet6 fe80::1c66:a0fa:d031:a192/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:c6:3b:76:cc brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c6ff:fe3b:76cc/64 scope link 
       valid_lft forever preferred_lft forever
5: veth747f1b9@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP 
    link/ether f2:c4:97:61:23:90 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::f0c4:97ff:fe61:2390/64 scope link 
       valid_lft forever preferred_lft forever

因為 Host 模式下 Docker 與 host 主機共享同一個 network namespace ,所以也就沒有定義如同 Bridge 的 IPAM (IP address management)., Container 沒有 IP 也沒有關係.

root@ubuntu:~# docker network inspect host
[
    {
        "Name": "host",
        "Id": "6b81378ae32ff195f16526e4f273ddf9907029af6a87232ae34b3d6c69d565db",
        "Scope": "local",
        "Driver": "host",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Containers": {
            "48db897c5311ab7637b7b40ebc6de446010acae90212587597275cbdeba3ad70": {
                "Name": "ubuntu-host",
                "EndpointID": "386c9f8b08ce2b5803af93d783c414728bddd489fdb2c563a9281c0b0d79500e",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

None

Container 預設為 Bridge 模式,如果要使用 None 模式需要在建立 Container 時透過 –network=none 來指定.

root@ubuntu:~# docker run --name ubuntu-none --network=none -t -i ubuntu:12.04 /bin/bash

一樣不管是透過 #ifconfig 或是 #brctl show 都沒有變化.None 所產生的 container 並不存在任何網絡環境,在 Container 內觀察也只有 loopback 裝置.

root@3fc84973782c:/# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

None 並沒有網路的定義, Container 也一樣.

root@ubuntu:~# docker network inspect none
[
    {
        "Name": "none",
        "Id": "5dd0460b223744278a1272a7d2b81608b0d6db884d13f1536935d8eb41b32814",
        "Scope": "local",
        "Driver": "null",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": []
        },
        "Internal": false,
        "Containers": {
            "3fc84973782c1b3674054f109877ec0e6e4ada45eaeda63a52278dbd0a3d2305": {
                "Name": "ubuntu-none",
                "EndpointID": "2255f965d7d7966fb92c248743e3e74e8ee46df5fcc292edf39f8e0c867d9a3c",
                "MacAddress": "",
                "IPv4Address": "",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

發表迴響