docker系列(三) docker的網絡模式之內部通信


簡介

關於docker的安裝文檔,請參照上篇文章<docker系列二在宿主機上的安裝和卸載>,本文主要針對docker中容器間的通信方式之內部通信進行說明。

容器間的通信

自從docker容器出現,容器的網絡通信一直是眾人關注的焦點,而容器的網絡方案又可以分為兩大部分:

  1. 單主機的容器間通信;
  2. 跨主機的容器間通信。

單主機Docker網絡通信

我們在使用docker run創建 Docker 容器時,可以使用--network=選項指定容器的網絡模式,Docker 有以下 4 種網絡模式:

  • host 模式,使用--network=host指定,不支持多主機;
  • bridge 模式,使用--network=bridge指定,默認設置,不支持多主機;
  • container 模式,使用--network=container:NAME_or_ID指定,即joiner 容器,不支持多主機;
  • none 模式,使用--network=none指定,不支持多主機。

bridge模式

bridge之使用默認網橋

當Docker進程啟動時,會在主機上創建一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連接到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網絡中。從docker0子網中分配一個 IP 給容器使用,並設置 docker0 的 IP 地址為容器的默認網關。在主機上創建一對虛擬網卡veth pair設備,Docker 將 veth pair 設備的一端放在新創建的容器中,並命名為eth0(容器的網卡),另一端放在主機中,以vethxxx這樣類似的名字命名,並將這個網絡設備加入到 docker0 網橋中。可以通過brctl show命令查看。安裝brctl命令:

yum install -y bridge-utils 
[root@linux-node4 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242d84b7159       no

bridge模式是 docker 的默認網絡模式,不寫–net參數,就是bridge模式。使用docker run -p時,docker 實際是在iptables做了DNAT規則,實現端口轉發功能。可以使用iptables -t nat -vnL查看。bridge模式如下圖所示:

實驗過程如下:

  • 步驟一:創建兩個容器
    docker run   --name docker1      nginx:1.13.12
    docker run -d --name docker2 nginx:1.13.12
    
  • 步驟二:查看機器上多了兩個veth虛擬網卡,查看網絡地址如我們之前說的一樣
[root@linux-node4 ~]# 
[root@linux-node4 ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242d84b7159       no              veth8c72f4a
                                                        vethf15e034
                         [root@linux-node4 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
75539117a127        nginx:1.13.12       "nginx -g 'daemon of…"   About an hour ago   Up About an hour    80/tcp              docker2
69f1c16d206c        nginx:1.13.12       "nginx -g 'daemon of…"   About an hour ago   Up About an hour    80/tcp              docker1    
[root@linux-node4 ~]# docker inspect 75539117a127 |grep 172.17
            "Gateway": "172.17.0.1",
            "IPAddress": "172.17.0.3",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.3",

bridge之使用自定義網橋

使用自定義的網橋

 docker network create -d bridge my-net4  --subnet=192.168.100.1/24

創建一個自定義網橋-d指定模式為bridge,也可以為overlay,--subnet指定子網范圍;
創建兩個容器,並連接到我們自建的網橋:

[root@linux-node4 ~]# docker run -d --name=my_test1  --network my-net4 nginx:1.13.12
ffc47de3992c52730ff2590b4b3903fe737521b9c713170d19b747fa2941c8b1

查看容器的網絡地址,驗證其ip地址是否是我們自定義的網絡。

[root@linux-node4 ~]# docker inspect ffc47de3992 |grep 192
                    "Gateway": "192.168.100.1",
                    "IPAddress": "192.168.100.2",

注意同一個網橋內的網絡是相互可以通信的,本篇不做過多說明。

host模式

如果啟動容器的時候使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個 Network Namespace。容器將不會虛擬出自己的網卡,配置自己的 IP 等,而是使用宿主機的 IP 和端口。但是,容器的其他方面,如文件系統、進程列表等還是和宿主機隔離的。 Host模式如下圖所示:

驗證步驟如下:

創建一個網絡類型為host的容器
docker run  -d --net=host --name=my_host1  nginx:1.13.12 

因為nginx容器本身的端口號是80,所以我們直接使用本地的接口來訪問宿主機的ip和端口號。

[root@linux-node4 ~]# !curl
curl http://127.0.0.1:80 
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

如果使用這種網絡模式的時候注意不要一個容器啟動多個實例,會引起端口沖突不能起來,這種網絡模型是無法使用nat轉化的。
host模式有利也有弊,主要包括以下缺點:

  • 容器沒有隔離、獨立的網絡棧:容器因為與宿主機共享網絡而爭搶資源,並且容易崩潰也可能導致主機崩潰,這在生產環境是不允許發生的;
  • 端口資源:docker host上已經使用的端口就不能再使用了
    host模式的優點如下:
  • 可以直接使用宿主機ip與外界通信,無需額外進行nat轉換,由於容器與外部通信,不再需要使用bridge等方式轉發或者進行數據包的封裝,性能上有很大優勢。

container模式

這個模式指定新創建的容器和已經存在的一個容器共享一個 Network Namespace,而不是和宿主機共享。新創建的容器不會創建自己的網卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。同樣,兩個容器除了網絡方面,其他的如文件系統、進程列表等還是隔離的。兩個容器的進程可以通過 lo 網卡設備通信。 Container模式示意圖:

我們還是通過實驗來驗證這個結論吧,上文我們已經創建了一個自定義網橋的容器,鏈接到這個容器里面即可

[root@linux-node4 ~]#  docker run -d --name docker_con3 --net=container:ffc47de3992c busybox sleep 6000 
933dd7fce1a67883869a6235c3a4f7835c983e079592087734715d05f6bd755e

進入容器內部驗證網絡是否跟預期一致:
[root@linux-node4 ~]# docker exec -it  933dd7fce1a6 sh     
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
33: eth0@if34: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:c0:a8:64:02 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.2/24 brd 192.168.100.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         192.168.100.1   0.0.0.0         UG    0      0        0 eth0
192.168.100.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0

None模式

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

[root@linux-node4 ~]#  docker run -d  --net=none  --name docker_none2  busybox  sleep 6000    
247fb9eace8b5dedcb47b7f2015eb06f18d4eb67eb323560dcfaaf7ef1069773
網絡情況驗證:
[root@linux-node4 ~]# docker exec -it  247fb9eace8b  /bin/sh 
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
/ # route -n 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
/ # 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM