測試環境為 Ubuntu16.04 ,關於 Docker 使用與設定請參考 https://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": {} } ]