天天看點

Docker容器網絡

Docker容器網絡

1、Docker容器網絡

Docker在安裝後自動提供3種網絡,可以使用``docker network ls`指令檢視

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
76170d3f9538   bridge    bridge     local
38bb8b947433   host      host      local
c74fce351c8a   none      null      local
           

Docker使用Linux橋接,在主控端虛拟一個Docker容器網橋(docker0),Docker啟動一個容器時會根據Docker網橋的網段配置設定給容器一個IP位址,稱為Container-IP,同時Docker網橋是每個容器的預設網關。因為在同一主控端内的容器都接入同一個網橋,這樣容器之間就能夠通過容器的Container-IP直接通信。

Docker 網絡管理指令

docker network connect			 #将容器連接配接到指定的網絡
docker network create			 #建立一個網絡
docker network disconnect		 #斷開容器與指定網絡的連接配接
docker network inspect			 #顯示一個或多個網絡的詳細資訊
docker network ls			 #顯示網絡清單
docker networkprune			 #删除所有未使用的網絡
docker network rm			 #删除一個或多個網絡
           

2、Docker的四種網絡模式

網絡模式 配置 說明
host --network host 容器和主控端共享Network namespace
container --network container:NAME_OR_ID 容器和另外一個容器共享Network namespace
none --network none 容器有獨立的Network namespace, 但并沒有對其進行任何網絡設定, 如配置設定veth pair 和網橋連接配接,配置IP等
bridge --network bridge 預設模式
# 使用busybox鏡像建立容器web1
[root@localhost ~]# docker run -dit --name web1 busybox 
3f96ace9c63f2863ca0c81ce8f933e2f0099c9a4902a8f4b4f4a111c9306e7ea

# 檢視主機ip位址
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:bb:22:82 brd ff:ff:ff:ff:ff:ff
    inet 192.168.111.135/24 brd 192.168.111.255 scope global dynamic noprefixroute ens160
       valid_lft 1221sec preferred_lft 1221sec
    inet6 fe80::3d5c:b9d6:55f:48e9/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:f0:ef:67:fd 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:f0ff:feef:67fd/64 scope link 
       valid_lft forever preferred_lft forever
5: vethdd490f4@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 0e:34:3e:de:8d:11 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::c34:3eff:fede:8d11/64 scope link 
       valid_lft forever preferred_lft forever
           
Docker容器網絡

2.1 bridge模式

當Docker程序啟動時,會在主機上建立一個名為docker0的虛拟網橋,此主機上啟動的Docker容器會連接配接到這個虛拟網橋上。虛拟網橋的工作方式和實體交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。

從docker0子網中配置設定一個IP給容器使用,并設定docker0的IP位址為容器的預設網關。在主機上建立一對虛拟網卡veth pair裝置,Docker将veth pair裝置的一端放在新建立的容器中,并命名為eth0(容器的網卡),另一端放在主機中,以vethxxx這樣類似的名字命名,并将這個網絡裝置加入到docker0網橋中。可以通過

brctl show

指令檢視。

bridge模式是docker的預設網絡模式,不寫--network參數,就是bridge模式。使用docker run -p時,docker實際是在iptables做了DNAT規則,實作端口轉發功能。可以使用

iptables -t nat -vnL

檢視。

bridge模式如下圖所示:

Docker容器網絡

假設上圖的docker2中運作了一個nginx,大家來想幾個問題:

  • 同主機間兩個容器間是否可以直接通信?比如在docker1上能不能直接通路到docker2的nginx站點?
  • 在主控端上能否直接通路到docker2的nginx站點?
  • 在另一台主機上如何通路node1上的這個nginx站點呢?DNAT釋出?

Docker網橋是主控端虛拟出來的,并不是真實存在的網絡裝置,外部網絡是無法尋址到的,這也意味着外部網絡無法通過直接Container-IP通路到容器。如果容器希望外部通路能夠通路到,可以通過映射容器端口到宿主主機(端口映射),即docker run建立容器時候通過 -p 或 -P 參數來啟用,通路容器的時候就通過[主控端IP]:[容器端口]通路容器。

# bridge模式
[root@localhost ~]# docker run -it --rm busybox
/ # ip a
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
6: eth0@if7: <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
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

(另起一個終端)
# 在使用互動模式進去進入busybox
[root@localhost ~]# docker run -it --rm busybox
/ # ip a
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
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.0.1      0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

# ping另一個(172.17.0.2)測試是否連通
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.201 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.127 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.127/0.164/0.201 ms

# ping主機(172.17.0.1)測試是否連通
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0 ttl=64 time=0.125 ms
64 bytes from 172.17.0.1: seq=1 ttl=64 time=0.096 ms
^C
--- 172.17.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.096/0.110/0.125 ms
           

2.2 container模式

這個模式指定新建立的容器和已經存在的一個容器共享一個 Network Namespace,而不是和主控端共享。新建立的容器不會建立自己的網卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口範圍等。同樣,兩個容器除了網絡方面,其他的如檔案系統、程序清單等還是隔離的。兩個容器的程序可以通過 lo 網卡裝置通信。

container模式如下圖所示:

Docker容器網絡
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
8293af30d1da   busybox   "sh"      5 seconds ago   Up 4 seconds             web1

# container模式
[root@localhost ~]# docker run -it --rm --network container:web1 busybox
/ # ip a
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
12: eth0@if13: <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
           

2.3 host模式

如果啟動容器的時候使用host模式,那麼這個容器将不會獲得一個獨立的Network Namespace,而是和主控端共用一個Network Namespace。容器将不會虛拟出自己的網卡,配置自己的IP等,而是使用主控端的IP和端口。但是,容器的其他方面,如檔案系統、程序清單等還是和主控端隔離的。

使用host模式的容器可以直接使用主控端的IP位址與外界通信,容器内部的服務端口也可以使用主控端的端口,不需要進行NAT,host最大的優勢就是網絡性能比較好,但是docker host上已經使用的端口就不能再用了,網絡的隔離性不好。

Host模式如下圖所示:

Docker容器網絡
# 容器和主控端共享Network namespace
[root@localhost ~]# docker run -it --rm --network host busybox
/ # ip a
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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel qlen 1000
    link/ether 00:0c:29:bb:22:82 brd ff:ff:ff:ff:ff:ff
    inet 192.168.111.135/24 brd 192.168.111.255 scope global dynamic noprefixroute ens160
       valid_lft 1031sec preferred_lft 1031sec
    inet6 fe80::3d5c:b9d6:55f:48e9/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue 
    link/ether 02:42:f0:ef:67:fd 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:f0ff:feef:67fd/64 scope link 
       valid_lft forever preferred_lft forever
13: vethd4e59b4@if12: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 
    link/ether de:9f:8a:68:b6:fc brd ff:ff:ff:ff:ff:ff
    inet6 fe80::dc9f:8aff:fe68:b6fc/64 scope link 
       valid_lft forever preferred_lft forever
           

2.4 none模式

使用none模式,Docker容器擁有自己的Network Namespace,但是,并不為Docker容器進行任何網絡配置。也就是說,這個Docker容器沒有網卡、IP、路由等資訊。需要我們自己為Docker容器添加網卡、配置IP等。

這種網絡模式下容器隻有lo回環網絡,沒有其他網卡。none模式可以在容器建立時通過--network none來指定。這種類型的網絡沒有辦法聯網,封閉的網絡能很好的保證容器的安全性。

應用場景:

  • 啟動一個容器處理資料,比如轉換資料格式
  • 一些背景的計算和處理任務

none模式如下圖所示:

Docker容器網絡
# none模式
[root@localhost ~]# docker run -it --rm --network none busybox
/ # ip a
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
           

檢視bridge網絡的詳細配置

[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "76170d3f9538f2d278789de3ea3bfa310db6e605a00e1615d453d083f6ad0c8b",
        "Created": "2022-08-09T20:26:03.696604937+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": {}
    }
]