Docker 網絡

容器虛擬化網絡基礎

docker安裝完之後,自動提供了3種網絡:html

  • bridge: 橋接網絡,Net橋
  • host: 共享宿主機的網絡接口
  • none: 容器內只有lo接口,沒有任何網卡
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9ac63d7fc6e8        bridge              bridge              local
b46032ae4b5f        host                host                local
60f69f2c7987        none                null                local
$

查看容器的網絡信息

使用 inspect 命令能夠查看docker對象的底層信息。好比能夠查看容器的信息,其中網絡部分的信息以下:node

"Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": n ll,
                    "NetworkID": "9ac63d7fc6e871eb47e39f9ec4e3fda6a23cb95a906a9ddc6431ed716e000fa1",
                    "EndpointID": "c8b64271d3d7ea5a0a8357c51fa5c80d398dbd07ad7e920792ebbaab628cb00d",
                    "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
                }
            }

這裏能夠查看容器內部網卡的IP地址。docker

共享網絡名稱空間

每個容器都有各自一組獨立的6個Namespaces:Mount、PID、User、UTS、IPC、Network。
還有一種方案,讓每個容器值只擁有獨立的Mount、PID、User。而其餘的3個UTS、IPC、Network是共享的。就是有本身隔離的名稱空間,但也能夠共享其中一部分名稱空間。通常只共享網絡通訊相關的,主機名(UTS)、進程間通訊(IPC)、網絡(Network)。
這樣作帶來了一個便利。如今不一樣的容器共享了網絡接口,使用的是同一個網絡。每一個容器內部的lo接口是同一個lo接口。這樣一個容器只要往本地的lo接口發請求,或者是往127.0.0.1發請求,共享網絡接口的其餘容器也可以接收到。shell

直接和宿主機共享名稱空間
仍是上面的共享名稱空間,還能夠直接和宿主機共享名稱空間。那麼這個和宿主機共享名稱空間的容器,容器內部的接口就是宿主機的網絡接口。容器對網絡的修改也就是對宿主機的網絡進行了修改。這個容器就有了管理網絡的特權。
這種就是網絡類型中的host類型,就是讓容器使用宿主機的網絡名稱空間。json

四種容器網絡類型

Docker一共有4種網絡模型數組

  • 封閉式
  • 橋接式
  • 聯盟式
  • 開放式

Docker 網絡

Bridged containers
橋接式容器通常擁有兩個接口:一個環回接口和一個鏈接至主機上某橋設備的以太網接口。
docker啓動時默認會建立一個名爲docker0的網絡橋,而且建立的容器爲橋接式容器,其以太網接口橋接至docker0。
docker0橋爲NET橋,所以橋接式容器可經過此橋接口訪問外部網絡。瀏覽器

Closed containers
不參與網絡通訊,運行於此容器中的進程僅能訪問本地環回接口。
僅適用於進程無須網絡通訊的場景中,例如備份、進程診斷及各類離線任務等。bash

設定容器網絡

建立容器時(run或create),使用參數能夠對容器的網絡進行設定。服務器

network 參數

使用--nework參數能夠指定容器的網絡模式,默認值是default,這個就是bridge模式。網絡

brideg模式
正常啓動容器,不使用任何網絡參數:

$ docker container run --name b1 --rm -it busybox
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12 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:1032 (1.0 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

以默認的網絡模式啓動容器。若是啓動容器是加上參數--network bridge效果也是同樣的。

none模式
使用--network none啓動一個沒有任何網絡的容器:

$ docker container run --name b1 --rm -it --network none busybox
/ # ifconfig -a
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

這裏顯示,只有一個lo接口,沒有其餘網絡接口。

其餘網絡模式
剩下的還有host模式和聯盟式網絡,這部分須要單獨再展開說明。

主機名和域名

在網絡上提供服務的時候,通常不是直接提供IP地址。而是提供主機名或域名,不但方便記憶也會有一些其餘的便利。因此Docker容器的主機名也是一個重要的網絡屬性。

主機名
容器的主機名就是它的ID:

/ # hostname
6fb514e1fa3b
/ #

能夠在啓動容器時,使用-h參數來設定容器的主機名:

$ docker container run --name b1 --rm -it -h b1.busybox busybox
/ # hostname
b1.busybox
/ #

DNS服務器
先看一下默認使用的DNS服務器,就是網關的地址:

/ # cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 192.168.1.1
/ # nslookup -type=a baidu.com
Server:         192.168.1.1
Address:        192.168.1.1:53

Non-authoritative answer:
Name:   baidu.com
Address: 220.181.38.148
Name:   baidu.com
Address: 123.125.114.144

/ #

使用參數指定DNS服務器啓動容器,而後查看容器的DNS的設置:

$ docker container run --name b1 --rm -it -h b1.busybox --dns 223.5.5.5 busybox
/ # cat /etc/resolv.conf 
nameserver 223.5.5.5
/ #

搜索域
另外還有個參數是--dns-search,是用來指定搜索域的。這個搜索域就是當給的名稱不是FQDN主機名格式的時候,自動補的後綴。

$ docker container run --name b1 --rm -it -h b1.busybox --dns 223.5.5.5 --dns-search baidu.com busybox
/ # cat /etc/resolv.conf 
search baidu.com
nameserver 223.5.5.5
/ # nslookup -type=a www
Server:         223.5.5.5
Address:        223.5.5.5:53

Non-authoritative answer:
www.baidu.com   canonical name = www.a.shifen.com
Name:   www.a.shifen.com
Address: 39.156.66.14
Name:   www.a.shifen.com
Address: 39.156.66.18

/ #

指定主機名的時候,沒有給完整的域名後綴,不過由於設置了搜索域,因此就自動補全了。

hosts文件
除了域名服務器,還能夠經過本地hosts文件來管理主機名:

$ docker container run --name b1 --rm -it -h busybox1.idx.net --dns 223.5.5.5 --dns-search idx.net busybox
/ # cat /etc/hosts
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      busybox1.idx.net busybox1
/ #

能夠看到默認就把主機名寫入到本地的hosts文件中了。這裏加了2個名稱,前一個是完整的主機名,後一個是主機名除去後綴的部分。
還可使用參數向hosts文件中注入信息:

$ docker container run --name b1 --rm -it -h busybox1.idx.net --dns 223.5.5.5 --dns-search idx.net --add-host host1.idx.net:192.168.100.1 --add-host host2.idx.net:192.168.100.2 busybox
/ # cat /etc/hosts 
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.100.1   host1.idx.net
192.168.100.2   host2.idx.net
172.17.0.2      busybox1.idx.net busybox1
/ #

添加記錄使用(host:ip)的格式。這個參數是list屬性,若是有多個記錄,就調用屢次參數。

端口映射-p

Docker0爲NET橋,所以容器得到的是私有網絡地址(內網地址)。
從拓撲結構上看,容器就是一臺在宿主機NET服務以後的一臺主機。若是容器須要對外提供服務,就要在宿主機上爲其定義DNAT規則。

-p選項的使用格式

-p <containerPort>

將指定的容器端口映射至主機全部地址的一個動態端口

-p <hostPort>:<containerPort>

將容器端口containerPort映射至主機端口hostPort

-p <ip>::<containerPort>

將指定的容器端口containerPort映射至主機指定ip的動態端口
命令中間是兩個冒號,至關於下面的3個變量的命令省略了中間的變量。

-p <ip>:<hostPort>:<containerPort>

將指定的容器端口containerPort映射至主機指定ip的端口hostPort

動態端口指隨機端口,具體映射結果可使用docker port命令查看

-P(大寫),隨機映射端口到內部容器開放的全部網絡端口。
這裏開放的網絡端口是鏡像製做時設定的,啓動容器時也可使用參數--expose指定計劃要開放的端口。只有使用-P參數,才須要指定具體要開放哪些端口,能夠是鏡像中設定也能夠是參數--expose設定。使用-p參數時,是指定要映射的端口,所處沒有設置要開放的端口也沒問題。

能夠指定使用的協議,默認是tcp。udp須要指定

-p 127.0.0.1:5000:5000/udp

-p參數能夠屢次使用來綁定多個端口

用httpd鏡像測試端口映射
不使用端口映射:

$ docker container run -dit --name app1 --rm httpd:alpine 
78e4e42fdd0c33a0410077731d26e418423a27827ab62e83dfe×××bca40f671
$ curl http://172.17.0.2
<html><body><h1>It works!</h1></body></html>
$ curl http://127.0.0.1
curl: (7) Failed connect to 127.0.0.1:80; 拒絕鏈接
$

因爲沒有作端口映射,容器能夠經過NAT訪問外部網絡,可是沒法被外部網絡訪問到,就是容器沒有暴露任何接口到公網。宿主機能夠經過容器的私網地址訪問頁面,可是沒法經過宿主機的接口地址訪問頁面,這樣外網也沒法訪問到頁面。

使用-P參數:

$ docker container run -dit --name app1 --rm -P httpd:alpine 
fde094cc000be912e68b8f6321f38d97c76cbabb54454da11c65e0aabd90dc1e
$ docker container port app1
80/tcp -> 0.0.0.0:32769
$ curl http://127.0.0.1:32769
<html><body><h1>It works!</h1></body></html>
$

此次能夠用個宿主機的環回口訪問了,直接用瀏覽器使用宿主機的地址也可以訪問。可是端口是隨機的,這就是須要使用port命令查看隨機分配的端口號。

聯盟式和開放式

聯盟式是容器之間共享網絡名稱空間,而開放式是容器共享使用宿主機的網絡名稱空間。在原理上這二者是同樣的。

聯盟式網絡

聯盟式容器(joined containrs),是指使用某個已經存在容器的網絡接口的容器。接口被聯盟內的各容器共享使用。
聯盟式容器彼此間共享的是同一個網絡名稱空間,UTS、IPC、Network。其餘名稱空間仍是隔離的,Mount、PID、User。
聯盟式容器彼此間存在端口衝突的可能性。所以,一般只會在多個容器上的程序須要程序loopback接口互相通訊、或對某已存的容器的網絡屬性進行監控時才使用此種模式的網絡類型。
介紹共享網絡名稱空間的時候,也講過共享後的便利,就是多個容器可使用本地環回口實現互相間的通訊。

啓動第一個容器
使用交互式接口,開啓一個容器:

$ docker container run --name b1 --rm -it busybox
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 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:516 (516.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

啓動第二個容器
上一個終端被佔用着,因此再開一個終端依然使用交互式接口開啓第二個容器。這裏多了--network參數,就是創建聯盟式容器的:

$ docker container run --name b2 --rm -it --network container:b1 busybox
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 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:656 (656.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

查看兩個容器的ip地址、MAC地址,可見兩個容器的網絡接口是同一個。效果就至關於傳統模式時,同一個主機裏的兩個進程。和傳統的模式相比,容器之間有更多個隔離。

聯盟式容器的應用場景
聯盟式容器能夠直接向本地的lo接口發送請求,聯盟的其餘容器也能夠收到這個請求,就比如聯盟中的容器是運行在同一個主機上的兩個進程同樣。
好比,首先有一個brideg模式的容器,提供一個靜態Web頁面的服務。而後對於動態頁面的請求則發送給另一個容器處理。
這時啓動第二個動態頁面的容器。若是這個容器也是brideg模式,因爲ip地址出動態得到的,那麼靜態頁面容器就沒法肯定向哪一個ip地址發送請求。此時若是這兩個容器是聯盟式的網絡,直接向本地的lo接口發送請求就能夠了。

開放式網絡

要使用開放式網絡,指定--network的參數爲host便可:

[root@Docker ~]# docker container run --name b3 --rm -it --network host busybox
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:3C:BE:06:75  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:3cff:febe:675/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:71 errors:0 dropped:0 overruns:0 frame:0
          TX packets:82 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:4773 (4.6 KiB)  TX bytes:7313 (7.1 KiB)

eth0      Link encap:Ethernet  HWaddr 00:15:5D:03:67:56  
          inet addr:192.168.24.170  Bcast:192.168.24.175  Mask:255.255.255.240
          inet6 addr: fe80::4c95:4028:8e1:a795/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:36462 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20392 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:42167574 (40.2 MiB)  TX bytes:1953899 (1.8 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:48 errors:0 dropped:0 overruns:0 frame:0
          TX packets:48 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:3777 (3.6 KiB)  TX bytes:3777 (3.6 KiB)

/ #

不要退出終端,繼續在容器裏開放一個httpd:

/ # echo "<h1>Hello b3, network host</h1>" > /var/www/index.html
/ # httpd -h /var/www/
/ # netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      
tcp        0      0 192.168.24.170:10010    0.0.0.0:*               LISTEN      
tcp        0      0 :::80                   :::*                    LISTEN      
tcp        0      0 :::22                   :::*                    LISTEN      
tcp        0      0 ::1:25                  :::*                    LISTEN      
/ #

啓動httpd服務後,也檢查了本地監聽端口,沒有問題。

防火牆問題
在宿主機上是能夠直接訪問這個Web頁面的:

$ curl 172.17.0.1
<h1>Hello b3, network host</h1>
$

可是外部網絡依然沒法訪問,這個主要是宿主機的防火牆問題。
以前也開放過服務,而且訪問都沒有問題。這個應該是宿主機將訪問容器的流量都默認放行了。而此次是要直接訪問宿主機,雖然服務是在容器內的,可是使用的網絡是宿主機的,因此須要防火牆放開策略。
臨時開放宿主機上的http服務

$ firewall-cmd --add-service=http
success
$ firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: ssh dhcpv6-client http
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

$

這個只是臨時測試,防火牆firewalld服務重啓後就會回覆原樣。
宿主機防火牆策略開放後,就可使用瀏覽器訪問宿主機的80端口打開頁面了。

開放式容器的應用場景
部署方式簡單,方便遷移。充分利用容器的優點,並能保證程序工做在宿主機上的要求,至少是經過宿主機的網絡接口對外提供服務。

以開放式容器的方式運行和進程差很少。都是在一個機器上運行多個進程。進程之間本來就是互相隔離的,可是使用容器後,還能夠隔離文件系統和用戶。另一個好處就是部署和遷移方便。以往工做爲宿主機首部進程的那些系統級管理的進程,之後就可使用容器的方式來運行。

修改默認docker網絡

上一節的內容是使用docker默認建立好的3個網絡,容器選擇其中一個網絡,並在運行容器時對可選的參數進行設置。
本節的內容是不使用默認提供的網絡,而是先對網絡進行自定義。自定義有兩種實現方式,一種是對默認的網絡進行修改,還有一種是徹底建立一個新的網絡。

默認的bridge網絡

默認設置,docker使用的是172.17.0.1/16的網絡。這個網絡的網絡類型是bridge,對應的網絡名稱也是bridge,對應在宿主機上的網卡是docker0。
使用ifconfig命令查看docker0橋的信息:

$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:3cff:febe:675  prefixlen 64  scopeid 0x20<link>
        ether 02:42:3c:be:06:75  txqueuelen 0  (Ethernet)
        RX packets 71  bytes 4773 (4.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 82  bytes 7313 (7.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

這個默認的dockr0橋接口是能夠修改的。另外還能夠額外定義新的橋接口網絡。

修改默認docker0橋

docker0橋是在docker daemon啓動時建立的,會根據默認屬性自動建立,也能夠經過修改配置文件來進行自定義。
配置文件就是/etc/docker/daemon.json,在添加鏡像加速器的時候已經用過了。主要的屬性有以下這些:

  • bip: docker0橋的ip地址和掩碼。docker會自動爲這個網絡配置一個dhcp
  • fixed-cidr: 限定爲容器分配的IP地址範圍
  • fixed-cidr-v6: 同上,ipv6地址的設置
  • mtu: 所能經過的最大數據包大小。通常爲1500,最好不要設置保持默認。
  • default-gateway: 默認網關
  • default-gateway-v6: 默認的ipv6網關
  • dns: dns服務器地址,能夠指定多個,這是一個數組類型

json配置內容示例:

{
    "bip": "192.168.10.1/24",
    "fixed-cidr": "192.168.10.128/25",
    "fixed-cidr-v6": "2001:db8::/64",
    "mtu": 1500,
    "default-gateway": "192.168.1.1",
    "default-gateway-v6": "2001:db8:abcd::89",
    "dns": ["114.114.114.114", "223.5.5.5"]
}

核心選項是bip(bridge ip),用於指定docker0橋自身的IP地址。根據須要進行自定義,能夠只設置一個bip,其餘保持默認。其餘選項會根據bip自動計算得出,還有一些是默認使用宿主機的網絡屬性。

實際修改本機的配置
修改後的配置文件以下:

{
    "registry-mirrors": ["http://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"],
    "bip": "192.168.101.1/24",
    "fixed-cidr": "192.168.101.128/25",
    "dns": ["114.114.114.114", "223.5.5.5"]
}

重啓服務後,先查看宿主機的docker0橋:

$ systemctl restart docker
$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.101.1  netmask 255.255.255.0  broadcast 192.168.101.255
        inet6 fe80::42:3cff:febe:675  prefixlen 64  scopeid 0x20<link>
        ether 02:42:3c:be:06:75  txqueuelen 0  (Ethernet)
        RX packets 81  bytes 5445 (5.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 92  bytes 8125 (7.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

此時docker0的網絡屬性已經變了。

新建容器查看網絡
建立容器,查看容器內的網絡屬性:

$ docker container run --name b4 --rm -it busybox
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:C0:A8:65:80  
          inet addr:192.168.101.128  Bcast:192.168.101.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 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:516 (516.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # cat /etc/resolv.conf 
nameserver 114.114.114.114
nameserver 223.5.5.5
/ # exit
$

這裏能夠確認到自動獲取的ip地址也符合設置要求了,還有dns服務器的地址也是自定義的。

建立自定義橋

查看已有的網絡:

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
8ec74d5bd709        bridge              bridge              local
d086953087bb        host                host                local
fa0c7f1fb6ca        none                null                local
$

查看網絡插件
這裏先展開一下,看看docker支持哪些類型的網絡。
命令docker info裏的插件Plugins的內容:

$ docker info
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog

在Network插件中,除了bridge、host、nul以外,還有overlay(疊加網絡)、macvlan(基於mac的vlan虛擬網絡),這兩種網絡類型沒有展開。這些網絡插件在下面建立網路時,經過-d參數能夠指定,默認是bridge。

建立網絡
使用命令docker network create命令來建立網絡:

$ docker network create -d bridge --subnet "192.168.111.0/24" mybr1

7128a28bbbf39a6ca483ecad03d5d85c8179507aff66ced73ca8de5233f16fee
[root@Docker ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
8ec74d5bd709        bridge              bridge              local
d086953087bb        host                host                local
7128a28bbbf3        mybr1               bridge              local
fa0c7f1fb6ca        none                null                local
[root@Docker ~]# ifconfig
br-7128a28bbbf3: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.111.1  netmask 255.255.255.0  broadcast 192.168.111.255
        ether 02:42:1f:ff:fd:5d  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.101.1  netmask 255.255.255.0  broadcast 192.168.101.255
        inet6 fe80::42:3cff:febe:675  prefixlen 64  scopeid 0x20<link>
        ether 02:42:3c:be:06:75  txqueuelen 0  (Ethernet)
        RX packets 81  bytes 5445 (5.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 92  bytes 8125 (7.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

-d參數能夠省略,默認就是bridge。更多的參數可使用--help選項查看:

  • --gateway: 設置網關
  • --ip-range: 等同fixed-cdir設置,從一個IP範圍分配IP地址
  • --internal: 限制外網網絡鏈接到這個網絡
  • --ipv6: 啓用ipv6網絡
  • --subnet: 等同bip設置,子網

指定網卡的名稱
在ifconfig查看的時候,網卡顯示的名稱是根據這個docker網絡額ID號自動生成的。在建立網絡時使用-o參數能夠進行指定:

$ docker network create --subnet "192.168.112.0/24" -o "com.docker.network.bridge.name=docker1" mybr2
b8a2639ce1baef83e54b5a0bca5ba6c7bbd2e6b607e62016c930350235bea965
$ ifconfig
br-7128a28bbbf3: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.111.1  netmask 255.255.255.0  broadcast 192.168.111.255
        ether 02:42:1f:ff:fd:5d  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.101.1  netmask 255.255.255.0  broadcast 192.168.101.255
        inet6 fe80::42:3cff:febe:675  prefixlen 64  scopeid 0x20<link>
        ether 02:42:3c:be:06:75  txqueuelen 0  (Ethernet)
        RX packets 81  bytes 5445 (5.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 92  bytes 8125 (7.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker1: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.112.1  netmask 255.255.255.0  broadcast 192.168.112.255
        ether 02:42:74:95:cd:0b  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

此次建立的網卡的名字就舒服多了。
關於-o參數,主要有下面這些:

選項 等同 描述
com.docker.network.bridge.name - 建立Linux bridge使用的bridge名稱
com.docker.network.bridge.enable_ip_masquerade ip-masq 啓用IP假裝
com.docker.network.bridge.enable_icc icc 啓用或禁用容器間鏈接
com.docker.network.bridge.host_binding_ipv4 ip 綁定容器端口時默認綁定的IP
com.docker.network.driver.mtu mtu 設置容器網絡MTU

這裏沒有網絡基礎可能不太好理解,不過咱們還能夠參考默認的bridge網絡的設置:

$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "80631c00ea3ece0280c786b90f5157be68fe76c26d52f4d9d870a7f5b59edde1",
        "Created": "2019-07-21T10:16:03.635792707+08:00",
        "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,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": 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": {}
    }
]
$

這個是默認的沒有修改過的bridge橋的信息。除了Options參數,其餘參數也能夠參考一下。

使用自定義網絡
這個以前已經用到過了。以前可選的網絡只有默認提供的3個,brideg、host、none,如今建立的自定義網絡也可使用了。命令docker network ls能夠查看,引用的時候使用--network參數指定網絡的名稱(NAME):

$ docker container run --rm -it --network mybr2 busybox
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:C0:A8:70:02  
          inet addr:192.168.112.2  Bcast:192.168.112.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12 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:1032 (1.0 KiB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

經過容器內的eth0的IP地址能夠判斷使用的是剛纔建立的自定義網絡。

遠程管理docker

docker守護進程是C/S構架,默認只監聽本機的UNIX sock文件。該文件位於/var/run/目錄下:

$ ls /var/run/*.sock
/var/run/docker.sock
$

能夠設置爲監聽TCP端口,這樣就可讓網絡上其餘主機上的客戶端鏈接到本地的服務端。

服務端配置

服務端須要修改配置文件,讓服務監聽網絡端口。配置文件/etc/docker/daemon.json添加一個hosts屬性:

{
    "hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]
}

修改配置文件後須要重啓服務。默認本地的UNIX sock文件仍是保留着。

客戶端鏈接

客戶端要鏈接到服務端,使用-H或--host參數來添加服務器。直接不帶任何參數執行docker命令,能夠查看到幫助信息:

-H, --host list          Daemon socket(s) to connect to

以前使用客戶端的時候,都是不帶這個參數的,也就是默認鏈接本機的UNIX sock文件。加上參數後,就能夠指定鏈接的服務端了。
使用-H參數,不過指定的服務器依然是本地的UNIX sock文件:

$ docker -H unix:///var/run/docker.sock network ls

若是開啓了網絡的監聽,能夠這樣:

$ docker -H 127.0.0.1 version

協議和端口號均可以省略,默認是tcp的2375端口。

不能指定多個服務器
看幫助,這個參數是個list,就是能夠屢次調用-H來添加多個服務端。參數是這麼設計的,可是程序的邏輯不容許:

$ docker -H unix:///var/run/docker.sock -H 127.0.0.1 images
Please specify only one -H
$

這裏找到了源碼中對應的處理函數:

func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error) {
    var host string
    switch len(hosts) {
    case 0:
        host = os.Getenv("DOCKER_HOST")
    case 1:
        host = hosts[0]
    default:
        return "", errors.New("Please specify only one -H")
    }

    return dopts.ParseHost(tlsOptions != nil, host)
}

參數只能是0個或1個,不然就返回錯誤。

設置環境變量
若是不使用-H參數指定,還能夠經過環境變量DOCKER_HOST指定。好處是不用每次鏈接都加上-H參數了。
下面是設置和驗證的命令:

$ export DOCKER_HOST="unix:///var/run/docker.sock"
$ echo $DOCKER_HOST
unix:///var/run/docker.sock
$

這裏設置的環境變量是臨時生效的,從新登陸就沒有了。若是想讓環境變量永久生效請寫入 ~/.bashrc 。

相關文章
相關標籤/搜索