Docker的網路管理

misakivv發表於2024-06-02

目錄
  • 一、Docker容器之間的通訊
    • 1、直接互聯(預設Bridge網路)
      • 1.1、Docker安裝後預設的網路配置
      • 1.2、建立容器後的網路配置
        • 1.2.1、首先建立一個容器
        • 1.2.2、ip a 列出網路卡變化資訊
        • 1.2.3、檢視新建容器後的橋接狀態
      • 1.3、容器內安裝常見的工具
      • 1.4、容器間通訊
    • 2、容器名稱互聯
      • 2.1、原理
      • 2.2、指令格式
      • 2.3、建立新的容器並引用已建立的容器
      • 2.4、進入容器檢視/etc/hosts檔案
      • 2.5、使用容器名稱互相通訊
    • 3、自定義容器別名互聯
      • 3.1、指令格式
      • 3.2、起別名的形式建立一個新的容器
      • 3.3、使用別名互相通訊
    • 4、自定義網路
      • 4.1、建立自定義網路
      • 4.2、啟動兩個容器並連線到自定義網路
      • 4.3、自定義網路進行容器間通訊
    • 5、Host網路模式
      • 5.1、啟動使用Host網路模式的容器
      • 5.2、使用Host網路模式進行通訊
    • 6、埠對映
      • 6.1、啟動帶有埠對映的容器
      • 6.2、其他容器訪問
  • 二、Docker的網路模式
    • 1、檢視預設的網路模式
    • 2、常見的五種網路模式
    • 3、Bridge網路模式
      • 3.1、Bridge網路模式的架構
      • 3.2、工作原理
        • 1、建立虛擬網橋
        • 2、IP地址分配與預設閘道器設定
        • 3、veth Pair裝置與網路接入
        • 4、網路名稱空間隔離
        • 5、與外部網路之間的通訊(SNAT)
        • 6、被外部主機訪問(DNAT)
        • 7、ip_forward功能
      • 3.3、Bridge網路模式的特點
      • 3.4、修改bridge網路的預設網段
        • 3.4.1、修改docker.service檔案
        • 3.4.2、修改daemon.json檔案
    • 4、Host網路模式
      • 4.1、Host網路模式的架構
      • 4.2、工作原理
      • 4.3、Host 網路模式的特點
      • 4.4、示例
        • 4.4.1、建立一個host網路模式的nginx容器
        • 4.4.2、再建立一個host網路模式的nginx容器
    • 5、none網路模式
      • 5.1、none網路模式架構
      • 5.2、工作原理
        • 1. 網路名稱空間隔離解除
        • 2. 僅有的網路介面:loopback
        • 3. 手動網路配置
      • 5.3、none網路模式的特點
      • 5.4、示例
        • 5.4.1、建立一個none網路模式的容器
        • 5.4.2、進入容器,檢視網路介面資訊並測試通訊能力
    • 6、Container網路模式
      • 6.1、Container網路模式架構
      • 6.2、工作原理
        • 1. 共享網路名稱空間
        • 2. 網路介面和IP地址
        • 3. 埠衝突
        • 4. 通訊方式
      • 6.3、Container網路模式的特點
      • 6.4、示例
        • 6.4.1、建立一個nginx容器
        • 6.4.2、建立一個新的container容器共享nginx的網路環境
        • 6.4.3、檢視兩個容器的ip地址
    • 7、自定義網路模式
      • 7.1、工作原理
      • 7.2、自定義網路的特點
      • 7.3、語法
        • 7.3.1、語法格式
        • 7.3.2、命令
        • 7.3.3、選項引數
      • 7.4、示例
      • 7.4.1、建立自定義網路
        • 7.4.2、使用自定義網路建立容器
        • 7.4.3、檢視容器的ip地址及對應的index.html檔案內容
        • 7.4.4、檢視網路
        • 7.4.5、自定義網路中容器的通訊
        • 7.4.6、檢視iptables相應的規則
  • 三、同一個宿主機間不同網路的容器通訊
    • 1、建立一箇中定義網路的容器
    • 2、再建立一個預設Bridge網路的容器
    • 3、測試兩個容器能否互相通訊
    • 4、解決方案
      • 4.1、修改iptables實現同一宿主機不同網路的容器通訊
      • 4.2、透過docker network connect 實現同一宿主機不同網路的容器通訊
    • 5、斷開不同網路中的容器通訊

一、Docker容器之間的通訊

1、直接互聯(預設Bridge網路)

1.1、Docker安裝後預設的網路配置

Docker服務安裝完成之後,預設在每個宿主機會生成一個名稱為docker0的網路卡其IP地址都是 172.17.0.1/16。

ip a | grep docker0

image-20240601210618497

1.2、建立容器後的網路配置

1.2.1、首先建立一個容器

[root@localhost ~]# docker run -itd --name nginx_v1 -p 8081:80 nginx

1.2.2、ip a 列出網路卡變化資訊

[root@localhost ~]# ip a
...
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:77:03:57:c7 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:77ff:fe03:57c7/64 scope link
       valid_lft forever preferred_lft forever
5: veth6ce240e@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether aa:8b:8e:1b:35:93 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::a88b:8eff:fe1b:3593/64 scope link
       valid_lft forever preferred_lft forever

image-20240601211831025

  • 建立了容器後

    • 宿主機就會多了一個虛擬網路卡,和容器的網路卡組合成一個網路卡,比如:5: veth6ce240e@if4,而在容器內的網路卡名為4,可以看出和宿主機的網路卡之間的關聯

    • 容器會自動獲取一個172.17.0.0/16網段的隨機地址,預設從172.17.0.2開始,第二個容器為 172.17.0.3,以此類推

    • 容器獲取的地址並不固定。每次容器重啟,可能會發生地址變化

1.2.3、檢視新建容器後的橋接狀態

[root@localhost ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242770357c7       no              veth6ce240e
  • bridge name: 顯示網橋的名稱,在這個例子中是docker0docker0是Docker在宿主機上自動建立的預設網橋,用於連線Docker容器到宿主機的網路。

  • bridge id: 每個網橋都有一個唯一的識別符號,通常格式為8000.<MAC地址>。在這個例子中,8000.0242770357c7docker0網橋的ID,其中02:42:77:03:57:c7是該網橋的MAC地址的一部分

  • STP enabled: 顯示是否啟用了Spanning Tree Protocol(STP,生成樹協議)。STP用於防止區域網中的橋接迴圈(bridge loops)和廣播風暴。輸出中的no表示在docker0網橋上STP是禁用的,這是Docker預設的行為,因為通常在容器環境中不需要STP。

  • interfaces: 列出了連線到該網橋的網路介面。在這個例子中,只有veth6ce240e這個介面連線到了docker0網橋。veth介面是一對虛擬乙太網裝置,通常一個在容器的網路名稱空間內(容器的eth0),另一個在宿主機的網路名稱空間內,它們透過這種方式橋接容器網路到宿主機網路,使得容器可以與宿主機及其他容器通訊。

  • 建立容器後容器會自動獲取ip地址

    [root@localhost ~]# docker exec -it nginx_v1 ip a
    

    image-20240601215513719

1.3、容器內安裝常見的工具

pingnslookupifconfigipcurl

監視系統狀態和管理程序的工具集合

apt install inetutils-ping -y
apt install dnsutils -y
apt install net-tools -y
apt install iproute2 -y
apt install curl -y
apt install procps -y

1.4、容器間通訊

預設情況下,同一個宿主機的不同容器之間可以相互通訊。

不同宿主機之間的容器IP地址重複,預設不能相互通訊。

在docker.service配置檔案中的fd://後面新增--icc=false 選項可以禁止同一個宿主機的不同容器間通訊。

  • 再建立一個容器進行互相通訊
[root@localhost ~]# docker run -itd --name nginx_v2 -p 8082:80 nginx
5e088a915221aef79d369bba6d76961598ea341222ae1c20d0cb1b8a0e1147f0
  • 分別獲取兩個容器對應的ip地址

    [root@localhost ~]# docker exec -it nginx_v1 hostname -i
    172.17.0.2
    [root@localhost ~]# docker exec -it nginx_v2 hostname -i
    172.17.0.3
    
  • 直接測試網路連通性

    [root@localhost ~]# docker exec -it nginx_v1 bash
    root@da9b2e5ecf77:/# ping 127.0.0.3 -c 3
    PING 127.0.0.3 (127.0.0.3): 56 data bytes
    64 bytes from 127.0.0.3: icmp_seq=0 ttl=64 time=0.068 ms
    64 bytes from 127.0.0.3: icmp_seq=1 ttl=64 time=0.096 ms
    64 bytes from 127.0.0.3: icmp_seq=2 ttl=64 time=0.087 ms
    --- 127.0.0.3 ping statistics ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max/stddev = 0.068/0.084/0.096/0.000 ms
    

2、容器名稱互聯

2.1、原理

  • docker run 建立容器,可使用--link選項實現容器名稱的引用

  • 其本質就是在容器內的/etc/hosts中新增--link後指定的容器的IP和主機名的對應關係,從而實現名稱解析。

2.2、指令格式

docker run --name	#先建立指定名稱的容器
docker run --link	#再建立容器時引用上面容器的名稱

2.3、建立新的容器並引用已建立的容器

[root@localhost ~]# docker run -itd --name nginx_test1 --link nginx_v1 -p 8083:80 nginx
eb9b74839c4c5e493df5fbfa5b0482cbc984e70a7ac7addcd9b01cce792d9449

2.4、進入容器檢視/etc/hosts檔案

[root@localhost ~]# docker exec -it nginx_test1 /bin/bash
root@eb9b74839c4c:/# 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      nginx_v1 cf9fc9d97972
172.17.0.4      eb9b74839c4c

2.5、使用容器名稱互相通訊

root@eb9b74839c4c:/# ping nginx_v1 -c 2
PING nginx_v1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.064 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.077 ms
--- nginx_v1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.064/0.071/0.077/0.000 ms

3、自定義容器別名互聯

自定義的容器名稱可能後期會發生變化,那麼一旦發生變化也會帶來一些影響,這個時候如果每次都更改名稱又比較麻煩

這個時候可以使用定義別名的方式解決,即容器名稱可以隨意更改,只要不更改別名即可。

3.1、指令格式

#先建立指定名稱的容器
docker run --name <容器名稱> 
docker run --name <容器名稱> --link <目標容器名稱>:"<容器別名1> <容器別名2> ..."

3.2、起別名的形式建立一個新的容器

[root@localhost ~]# docker run -itd --name nginx_test2 -p 8084:80 --link nginx_v2:nginx_v2_alias nginx
3382790d21e3224c50799e907b229185fb5ab37140b51cc6ab4536e19c00dabd
  • --link nginx_v2:nginx_v2_alias: 設定容器間的連結。
  • 這裡表示當前新建立的容器將與名為 nginx_v2 的容器建立連結,並且在新容器內部,這個連結將以 nginx_v2_alias 的別名存在。
  • 連結允許容器之間相互通訊,並且可以使用別名透過環境變數等方式訪問被連結容器的資訊。

3.3、使用別名互相通訊

docker exec -it nginx_test2 ping -c 2 nginx_v2_alias

image-20240602085657009

4、自定義網路

4.1、建立自定義網路

[root@localhost ~]# docker network create my_network
0c93f493d62d5791febeb088048f85874e9ae2bc9266bb84f88f4864ad379d46
[root@localhost ~]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
4d478ce25a22   bridge       bridge    local
738397fc865f   host         host      local
0c93f493d62d   my_network   bridge    local
75326f81366f   none         null      local

當我們建立了一個自定義網路(my_network)Docker 會建立一個新的橋接網路(bridge driver)。

其底層技術仍然是基於橋接網路實現的,即每個連線到此自定義網路的容器都會獲得一個虛擬網路卡,並透過Docker管理的一個虛擬網橋(類似於預設的bridge網路所使用的網橋)與其他容器以及宿主機進行通訊。

4.2、啟動兩個容器並連線到自定義網路

[root@localhost ~]# docker run -itd --name nginx_network3 --network my_network nginx
c98ca358f48e945a9d6b9f4d0c54e562cbbf1aef58e2a265bf2f40296cecb923
[root@localhost ~]# docker run -itd --name nginx_network4 --network my_network nginx
c0e09ba99d47652eb4755b7d4e5c1c676fd1f7e4a52a93a55865475c001ae0ea

4.3、自定義網路進行容器間通訊

[root@localhost ~]# docker exec nginx_network3 ping -c 2 nginx_network4

image-20240602092239013

5、Host網路模式

5.1、啟動使用Host網路模式的容器

使用Host網路模式,容器直接使用宿主機的網路棧

host 網路模式下,容器直接使用宿主機的網路棧,沒有獨立的網路名稱空間,因此容器內部的服務就直接監聽在宿主機的網路介面上,不再需要埠對映。

[root@localhost ~]# docker run -itd --name nginx_host -p 8086:80 --network host nginx

image-20240602094043377

可以看到Docker是會忽略--network host模式啟動容器時指定的埠對映的

5.2、使用Host網路模式進行通訊

此時其他容器就可以透過宿主機的ip和埠進行訪問

docker exec -it nginx_v1 ping -c 2 192.168.112.60

image-20240602094358276

6、埠對映

6.1、啟動帶有埠對映的容器

這裡的映象mycentos_nginx:v1用的是之前Docker製作映象中的使用DockerFile製作的nginx映象

[root@localhost ~]# docker run -itd --name nginx_port -p 8090:80 mycentos_nginx:v1

6.2、其他容器訪問

[root@localhost ~]# docker exec -it nginx_v3 curl -s 192.168.112.60:8090
#發現可以獲取到之前定義的index.html檔案內容

image-20240602111211694

二、Docker的網路模式

1、檢視預設的網路模式

[root@localhost ~]# docker network ls

image-20240602163023301

預設會生成三種不同的網路

bridgehostnull

2、常見的五種網路模式

Docker網路模式 配置 說明
bridge模式 –net=bridge(預設) 為每個容器分配獨立的網路名稱空間和IP地址,透過Docker虛擬網橋(docker0)與宿主機及其它容器通訊。
host模式 –net=host 容器直接使用宿主機的網路名稱空間,無獨立IP,容器和服務直接透過宿主機的網路介面和埠暴露。
none模式 –net=none 容器僅有lo(迴環)介面,無網路配置,適用於不需要網路的場景。
container模式 –net=container:NAME_or_ID 新容器共享指定容器的網路名稱空間,包括IP地址和埠範圍,適用於緊密網路耦合的場景。
User-defined(使用者自定義) docker network create <網路名> --net=<網路名> 建立自定義網路,可以配置網路驅動、子網、IP範圍等,提供更靈活的網路控制,適用於微服務架構等複雜網路需求。

3、Bridge網路模式

3.1、Bridge網路模式的架構

image-20240602185111364

3.2、工作原理

1、建立虛擬網橋

  • Docker啟動時自動建立名為docker0的虛擬網橋,作為容器間及容器與宿主機通訊的基礎。
  • 所有在同一宿主機上啟動的Docker容器預設連線到這個虛擬網橋,模擬物理交換機行為,形成二層網路。

2、IP地址分配與預設閘道器設定

  • 從docker0網橋關聯的子網中動態分配IP地址給新建立的容器使用。
  • 設定docker0的IP地址作為容器的預設閘道器,確保容器對外通訊的路由正確。

3、veth Pair裝置與網路接入

  • 在宿主機和容器間建立一對虛擬乙太網裝置(veth pair),實現容器網路棧與宿主機網路棧的連線。
  • veth pair的一端(eth0)置於容器內作為其網路介面,另一端(vethxxx)留在宿主機並加入docker0網橋,完成容器網路接入。

4、網路名稱空間隔離

  • 每個Docker容器都執行在自己的網路名稱空間中,這意味著它們有自己獨立的網路配置,包括網路卡、IP地址、路由表等,彼此之間互不影響,增強了容器之間的隔離性。

5、與外部網路之間的通訊(SNAT)

  • 當Docker容器嘗試訪問外部網路(如訪問網際網路)時,由於容器的IP地址是私有的(屬於docker0網橋的子網),直接訪問外部網路會遇到路由問題。此時,宿主機上的網路棧會介入,透過源地址轉換(Source Network Address Translation, SNAT)技術,將容器發出的資料包的源IP地址替換為宿主機的公網IP地址,從而使得資料包能夠順利透過路由器併到達目標伺服器。這一過程使得容器能夠透明地訪問外部網路資源。

6、被外部主機訪問(DNAT)

  • 要使外部主機能夠訪問容器內的服務,Docker透過目的地址轉換(Destination Network Address Translation, DNAT)實現。當你使用docker run -p命令將容器埠對映到宿主機埠時,Docker會在宿主機的iptables規則中設定DNAT條目,將指向宿主機特定埠的流量重定向到容器內的相應埠。這意味著外部客戶端可以使用宿主機的IP地址和對映的埠號來訪問容器內的服務。

7、ip_forward功能

  • 為了使上述SNAT和DNAT能夠正常工作,宿主機需要啟用IP轉發功能。IP轉發允許宿主機作為網路中間節點,將接收到的資料包轉發到其他網路介面或裝置,這對於容器透過宿主機路由進出流量至關重要。通常,可以透過編輯/etc/sysctl.conf檔案(增加或修改net.ipv4.ip_forward=1)並執行sysctl -p命令來啟用這一功能。

  • [root@localhost ~]# cat /proc/sys/net/ipv4/ip_forward
    1
    

    安裝Docker後會預設啟用ip_forward

3.3、Bridge網路模式的特點

  • 網路資源隔離:不同宿主機的容器無法直接通訊,各自使用獨立網路
  • 無需手動配置:容器預設自動獲取172.17.0.0/16的IP地址,此地址可以修改
  • 可訪問外網:利用宿主機的物理網路卡,SNAT連線外網
  • 外部主機無法直接訪問容器:可以透過配置DNAT接受外網的訪問
  • 效能較低:因為可透過NAT,網路轉換帶來更的損耗
  • 埠管理繁瑣:每個容器必須手動指定唯一的埠,容器產生埠衝突

3.4、修改bridge網路的預設網段

有兩種方式可以修改bridge網路的預設網段,但是兩種只能選擇一種,否則docker服務無法啟動

3.4.1、修改docker.service檔案

修改配置檔案前記得備份,前面跟著做的就不需要重複備份了

[root@localhost ~]# vim /usr/lib/systemd/system/docker.service
...
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=172.10.0.1/16
...
#修改為172.10網段

[root@localhost ~]# systemctl daemon-reload && systemctl restart docker
[root@localhost ~]# docker run -itd --name nginx_v4 -p 8091:80 mycentos_nginx:v1
[root@localhost ~]# docker run -itd --name nginx_v5 -p 8092:80 mycentos_nginx:v1
#建立兩個容器來驗證網段是否修改

[root@localhost ~]# docker inspect nginx_v4 --format='{{json .NetworkSettings.IPAddress}}'
"172.10.0.2"
[root@localhost ~]# docker inspect nginx_v5 --format='{{json .NetworkSettings.IPAddress}}'
"172.10.0.3"
#可以看到再建立的容器分配到的ip地址就是172.10網段的ip,且從172.10.0.2往後順延

3.4.2、修改daemon.json檔案

沒有這個檔案的是沒有開啟映象加速功能

阿里雲映象加速 -> 容器映象服務 -> 映象工具 -> 映象加速器 依據操作文件新增

[root@localhost docker]# cat /etc/docker/daemon.json
{
  "registry-mirrors": ["https://jzjzrggd.mirror.aliyuncs.com"],
  "bip": "172.72.0.1/16",
  "dns": ["8.8.8.8"]
}
#這裡我將預設網段修改為172.72

[root@localhost docker]# systemctl daemon-reload && systemctl restart docker
[root@localhost ~]# docker run -itd --name nginx_v6 -p 8093:80 mycentos_nginx:v1
0dba43ccae42824f0c3bbd80617de2c2685dc8c9a6120c416047b43fe4f90cdd
[root@localhost ~]# docker run -itd --name nginx_v7 -p 8094:80 mycentos_nginx:v1
2fa22556636d2d223bfe0ca8a0d961dd8f88671fb018b4095f1a86d02c9babe7
#建立兩個容器來驗證網段是否修改

[root@localhost ~]# docker exec -it nginx_v6 hostname -i
172.72.0.2
[root@localhost ~]# docker exec -it nginx_v7 hostname -i
172.72.0.3
#可以看到再建立的容器分配到的ip地址就是172.72網段的ip,且從172.72.0.2往後順延

image-20240602181248971

注意:由於之前示例的容器均沒有固定ip以及設定隨docker自啟所以以上操作會導致用於示例的容器都是Exited (0)狀態,並且重啟容器後ip地址也會從新設定的網段開始分配

4、Host網路模式

4.1、Host網路模式的架構

image-20240602192049352

4.2、工作原理

  • 網路名稱空間共享:容器不再擁有獨立的網路介面、IP地址、路由表等,而是直接使用宿主機的網路配置,包括網路介面卡(NIC)、IP地址、埠等。
  • 埠和網路服務:容器內的服務可以直接透過宿主機的IP地址和埠訪問,無需進行埠對映,因為容器與宿主機網路完全一致。
  • 效能:由於沒有網路棧的額外開銷,Host模式下的容器網路效能通常優於其他網路模式。
  • 安全性與隔離性:這是Host模式的最大劣勢,容器失去了網路層面的隔離保護,容器內的服務與宿主機服務在同一個網路環境中,存在潛在的安全風險,且容器間也無網路隔離。

4.3、Host 網路模式的特點

  • 共享宿主機網路
  • 網路效能無損耗
  • 網路故障排除相對簡單
  • 各容器網路無隔離
  • 網路資源無法分別統計
  • 埠管理困難,容易產生埠衝突
  • 不支援埠對映
  • 適用於執行容器埠比較固定的業務

4.4、示例

4.4.1、建立一個host網路模式的nginx容器

[root@localhost ~]# docker run -itd --name nginx_v8 --network host mycentos_nginx:v1
0d61e812c6c82d86b87fe89649c3c99768c9a2b794c81ecf902fdace092cc331

[root@localhost ~]# ss -tnl | grep 80
#可以看到宿主機的80埠開啟

image-20240602204918333

4.4.2、再建立一個host網路模式的nginx容器

[root@localhost ~]# docker run -itd --name nginx_v9 --network host -p 8095:80 mycentos_nginx:v1

image-20240602205303381

可以看到再建立nginx容器就會出現埠衝突的情況

也無法使用埠對映,因為是公用宿主機的80埠

5、none網路模式

5.1、none網路模式架構

image-20240602213453911

5.2、工作原理

1. 網路名稱空間隔離解除

在None模式下,雖然容器仍然有自己的網路名稱空間,但這個名稱空間內幾乎為空,Docker不會為容器配置任何網路介面、IP地址或路由規則。這意味著容器沒有網路連線能力,既不能訪問宿主機網路,也不能與其他容器通訊。

2. 僅有的網路介面:loopback

在None模式下啟動的容器,內部通常只包含迴環介面(lo),即localhost,用於容器內部的程序間通訊。這意味著容器內的服務只能透過localhost地址互相訪問,但無法與宿主機或外部網路通訊。

3. 手動網路配置

雖然None模式下的容器沒有預設的網路配置,但使用者可以根據需要手動配置網路。這意味著可以使用ip命令或相關指令碼為容器內的網路介面新增IP地址、配置路由規則等,使其能夠連線到特定網路。這通常涉及建立虛擬乙太網對(veth pairs)並將其中一端放入容器,然後手動配置網路引數。

5.3、none網路模式的特點

  • 安全隔離:對於不需要網路連線的容器,使用None模式可以增強安全性,減少攻擊面。
  • 定製化網路:當需要構建非常特定的網路配置,如點對點通訊、直接與宿主機的特定網路介面相連等,可以在None模式基礎上手動配置網路。
  • 除錯與測試:在排除網路問題或進行網路相關的單元測試時,可以使用None模式建立一個乾淨、無網路干擾的環境。

5.4、示例

5.4.1、建立一個none網路模式的容器

[root@localhost ~]# docker run -itd --name nginx_v10 -p 8096:80 --network none mycentos_nginx:v1

5.4.2、進入容器,檢視網路介面資訊並測試通訊能力

[root@localhost ~]# docker exec -it nginx_v10 bash
[root@49d500bcbc3a /]# 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
[root@49d500bcbc3a /]# ping www.baidu.com
ping: www.baidu.com: Name or service not known
[root@49d500bcbc3a /]# ping 172.17.0.1
connect: Network is unreachable
#可以看到網路介面資訊只有lo介面,無法與外部通訊

image-20240602211351451

6、Container網路模式

6.1、Container網路模式架構

image-20240602213805900

6.2、工作原理

1. 共享網路名稱空間

  • 當使用 --net=container:NAME_or_ID 引數啟動一個容器時,Docker 不會為新容器建立新的網路名稱空間,而是讓它與指定容器共享同一個網路名稱空間。
  • 這意味著兩個容器看網路的角度是完全一樣的,就像它們是在同一臺機器上執行一樣,共享相同的網路配置和網路資源。

2. 網路介面和IP地址

  • 新容器不會獲得自己的網路介面和IP地址,它直接使用被共享容器的網路介面和IP地址。
  • 兩個容器可以訪問相同的網路服務,如同一區域網內的兩臺電腦,無需額外的埠對映或網路配置。

3. 埠衝突

  • 由於共享網路名稱空間,兩個容器不能繫結到同一個埠上執行服務,否則會出現埠衝突。
  • 如果需要在多個容器中執行相同服務,應考慮使用其他網路模式,如Bridge模式,並透過埠對映解決衝突。

4. 通訊方式

  • 容器間通訊非常直接,因為它們共享相同的網路環境,透過localhost或容器內的IP即可互相訪問。
  • 對於外部訪問,由於它們共享宿主機的網路棧,所以外部訪問也遵循與共享容器相同的規則,例如,如果共享容器有埠對映到宿主機,則新容器的服務也可透過這些對映埠訪問。

6.3、Container網路模式的特點

  • 與宿主機網路空間隔離
  • 容器間共享網路空間
  • 適合頻繁的容器間的網路通訊
  • 直接使用對方的網路,較少使用
  • 主要用於需要緊密網路耦合的場景,如微服務架構中某些服務間的直接通訊。

6.4、示例

6.4.1、建立一個nginx容器

[root@localhost ~]# docker run -itd --name nginx_v11 -p 8098:80 mycentos_nginx:v1        06810ca19da88562cd539f7bd9dff8b8030bc64628760e28f8f4204ced5135b3

6.4.2、建立一個新的container容器共享nginx的網路環境

[root@localhost ~]# docker run -itd --name container_v1 --network container:nginx_v11 centos:7

6.4.3、檢視兩個容器的ip地址

[root@localhost ~]# docker exec -it nginx_v11 hostname -i                                
172.72.0.10
[root@localhost ~]# docker exec -it container_v1 hostname -i
172.72.0.10

image-20240602221202465

7、自定義網路模式

7.1、工作原理

  1. 網路名稱空間:每個連線到自定義網路的容器都會有自己的網路名稱空間,確保網路資源(如網路介面、路由表等)的隔離。
  2. 網路橋接:Docker使用網路驅動(通常是Bridge驅動)建立一個或多個虛擬網橋,容器的網路介面透過虛擬網橋與宿主機的網路介面相連,實現容器間以及容器與宿主機的通訊。
  3. IP地址管理:Docker會根據指定的子網為每個容器分配一個靜態或動態IP地址,並管理網路配置,如閘道器、DNS伺服器等。
  4. 服務發現:Docker透過內建的DNS服務或外部服務發現機制,使得容器可以透過名稱查詢其他容器的IP地址,簡化配置。

7.2、自定義網路的特點

  • 靈活性:使用者可以自定義網路的配置,包括子網、IP地址、DNS設定等,滿足複雜應用的網路需求。
  • 可擴充套件性:隨著應用規模擴大,可以透過Overlay網路驅動實現跨主機容器通訊,擴充套件網路覆蓋範圍。
  • 隔離性:每個自定義網路都是獨立的,提供容器間以及與宿主機的網路隔離,增加安全性。
  • 易管理性:透過Docker CLI輕鬆建立、刪除、連線或斷開容器與網路的關聯,便於網路運維。

7.3、語法

7.3.1、語法格式

docker network COMMAND
docker network create -d <mode> --subnet <CIDR> --gateway <閘道器> <自定義網路名稱>

mode不支援host和none,預設是bridge模式

7.3.2、命令

Commands:
• connect 將容器連線到網路
• create  建立網路
• disconnect斷開容器與網路的連線
• inspect 顯示一個或多個網路的詳細資訊
• ls 列出網路列表
• prune 刪除所有未使用的網路
• rm 刪除一個或多個網路

7.3.3、選項引數

[options]
--driver 或 -d: 指定網路的驅動型別。預設是 bridge,但也可以是 overlay、macvlan、ipvlan 等。例如,建立一個 overlay 網路:--driver overlay。

--subnet: 指定網路的子網。可以多次指定以建立多個子網。例如,--subnet=172.16.23.0/24。

--gateway: 設定網路的預設閘道器地址。例如,--gateway=172.16.23.1。

--ip-range: 限制Docker從指定的子網範圍內分配IP地址給容器。這對於大型網路很有用。

--opt: 傳遞特定於驅動程式的選項。例如,對於 overlay 驅動,可以設定 --opt encrypted 來加密網路通訊。

--internal: 將網路配置為內部網路,意味著外部流量不能到達此網路上的容器。

--attachable: 允許後續的容器即使在建立網路時沒有指定也能連線到這個網路。

--label: 新增後設資料標籤到網路,用於過濾和識別。格式為 key=value。

--scope: 設定網路的作用域,通常是 local(單個Docker主機)或 global(Swarm模式下)。預設為 local。

--ingress: (Swarm模式特有)建立一個特殊的Ingress網路,用於Swarm服務的外部流量路由。

7.4、示例

7.4.1、建立自定義網路

[root@localhost ~]# docker network create -d bridge --subnet 172.172.0.0/16 --gateway 172.172.0.1 net-test

[root@localhost ~]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
3593c2126bf2   bridge       bridge    local
738397fc865f   host         host      local
0c93f493d62d   my_network   bridge    local
8f95cd5b3ac0   net-test     bridge    local
75326f81366f   none         null      local

此時會新新增一個虛擬網路卡和網橋

image-20240602231251968

brctl show檢視新的虛擬網路卡對應的interfaces顯示為空。

image-20240602231344194

7.4.2、使用自定義網路建立容器

[root@localhost ~]# docker run -itd --name nginx_v13 --network net-test -p 8099:80  mycentos_nginx:v1
a9e35a0b3d86caeef38501c5c45c62d753ac31e650f231e2bd41d4c34b03ed4c

7.4.3、檢視容器的ip地址及對應的index.html檔案內容

[root@localhost ~]# docker exec -it nginx_v13 hostname -i
172.172.0.2
[root@localhost ~]# curl 172.172.0.2
test nginx !
[root@localhost ~]# docker exec -it nginx_v13 cat /usr/local/nginx/html/index.html
test nginx !

7.4.4、檢視網路

[root@a9e35a0b3d86 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.172.0.2  netmask 255.255.0.0  broadcast 172.172.255.255
        ether 02:42:ac:ac:00:02  txqueuelen 0  (Ethernet)
        RX packets 17  bytes 1285 (1.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 670 (670.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        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

7.4.5、自定義網路中容器的通訊

[root@a9e35a0b3d86 /]# ping -c 2 www.baidu.com
PING www.a.shifen.com (180.101.50.188) 56(84) bytes of data.
64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=1 ttl=127 time=8.85 ms
64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=2 ttl=127 time=8.53 ms

--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 8.535/8.694/8.854/0.184 ms

image-20240602232422341

7.4.6、檢視iptables相應的規則

[root@localhost ~]# iptables -t nat -nvL

image-20240602233034776

PREROUTING 和 OUTPUT 鏈中的DOCKER規則

  • 規則允許所有目的地址為本地(dst-type LOCAL)的資料包進入,並將其標記為DOCKER流量,這是為了確保發往本地並且最終目標是Docker容器的流量能夠被正確處理。
  • 在OUTPUT鏈中,有規則指明所有出站流量如果不是發往127.0.0.0/8(即本地迴環),且目標是本地的,也會被標記為DOCKER流量。

POSTROUTING 鏈中的MASQUERADE規則

  • 多個MASQUERADE規則用於將來自不同子網(如172.172.0.0/16172.18.0.0/16)的流量偽裝成主機的IP地址,以便容器可以透明地訪問外部網路。這表明容器對外通訊時,它們的源IP會被替換為主機的外網IP。
  • 特定於埠(如tcp dpt:80)的MASQUERADE規則似乎是重複的,它們可能是因為對特定容器埠進行了埠對映配置,但目前沒有匹配的DNAT規則對應,看起來可能是配置錯誤或歷史殘留。

DOCKER鏈中的規則

  • RETURN規則指示當資料包來自於特定的Docker網路介面(如br-8f95cd5b3ac0, docker0, br-0c93f493d62d)時直接返回,這通常意味著這些網路內部的流量不需要進一步處理。
  • DNAT(Destination NAT,目標地址轉換)規則將到達主機的特定埠(例如8094至8099)的資料包轉發到對應的容器內埠80上。這展示了埠對映配置,允許外部訪問容器的服務。

三、同一個宿主機間不同網路的容器通訊

1、建立一箇中定義網路的容器

[root@localhost ~]# docker run -itd --name nginx_v14 --network net-test -p 8100:80 mycentos_nginx:v1
515a5a6a1574ae7d0d14e273de3ba1750024648d7a1bbad0bfb12af4ae264952

2、再建立一個預設Bridge網路的容器

[root@localhost ~]# docker run -itd --name nginx_v15 -p 8101:80 mycentos_nginx:v1
4da77959831e67950a5522c02f225c0470beee0802780ce2d20754707f2eabf1

3、測試兩個容器能否互相通訊

[root@localhost ~]# docker exec -it nginx_v14 hostname -i
172.172.0.2
[root@localhost ~]# docker exec -it nginx_v15 hostname -i
172.72.0.2
[root@localhost ~]# docker exec -it nginx_v15 bash
[root@4da77959831e /]# ping 172.172.0.2
PING 172.172.0.2 (172.172.0.2) 56(84) bytes of data.
^C
--- 172.172.0.2 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6032ms

image-20240603081407449

顯然ping不通

4、解決方案

4.1、修改iptables實現同一宿主機不同網路的容器通訊

iptables-save > iptables.rule
#怕改錯的也可以備份一份

vim iptables.rule
#修改下面兩行的規則 
-A DOCKER-ISOLATION-STAGE-2 -o br-8f95cd5b3ac0 -j ACCEPT 
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j ACCEPT

iptables-restore < iptables.rule

image-20240603082642151

這其中的br-8f95cd5b3ac0可以使用iptables -nvL | grep 172.172.0.2過濾檢視(剛才使用自定義網路建立容器的ip地址)

[root@localhost ~]# docker exec -it nginx_v14 hostname -i
172.172.0.2
[root@localhost ~]# docker exec -it nginx_v15 hostname -i
172.72.0.2
[root@localhost ~]# docker exec -it nginx_v15 bash
[root@4da77959831e /]# ping -c 2 172.172.0.2
PING 172.172.0.2 (172.172.0.2) 56(84) bytes of data.
64 bytes from 172.172.0.2: icmp_seq=1 ttl=63 time=0.060 ms
64 bytes from 172.172.0.2: icmp_seq=2 ttl=63 time=0.087 ms

--- 172.172.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1011ms
rtt min/avg/max/mdev = 0.060/0.073/0.087/0.016 ms

image-20240603083218020

可以通訊

4.2、透過docker network connect 實現同一宿主機不同網路的容器通訊

做這個操作前記得將之前的iptables規則改回去哦

#將CONTAINER連入指定的NETWORK中,使此CONTAINER可以與NETWORK中的其它容器進行通訊 
docker network connect [OPTIONS] NETWORK CONTAINER
Options:
--alias strings 為容器新增網路範圍的別名
--driver-opt strings 網路的驅動程式選項
--ip string IPv4地址 (e.g:172.30.100.104)
--ip6 string IPv6 地址 (e.g:2001:db8::33)
--link list 將連結新增到另一個容器
--link-local-ip strings 為容器新增連結本地地址
#將Bridge網路模式的容器nginx_v15可以連到自定義網路net-test的容器nginx_v14
[root@localhost ~]# docker network connect net-test nginx_v15
docker exec -it nginx_v15 ping -c 2 172.172.0.2
#測試通訊,nginx_v15可以ping通nginx_v14

docker exec -it nginx_v14 ping -c 2 172.72.0.2
#但是自定義網路的nginx_v14ping不通nginx_v15
docker network connect bridge nginx_v14
#將自定義網路的nginx_v14可以連通預設Bridge網路的nginx_v15
將Bridge網路模式的容器nginx_v15可以連到自定義網路net-test的容器nginx_v14
image-20240603084456369
測試通訊,nginx_v15可以ping通nginx_v14,但是自定義網路的nginx_v14ping不通nginx_v15
image-20240603084816198
將自定義網路的nginx_v14可以連通預設Bridge網路的nginx_v15
image-20240603085238250

5、斷開不同網路中的容器通訊

docker network disconnect net-test nginx_v15
#斷開nginx_v15容器與net-test網路中其他容器的通訊
#此時預設Bridge網路的nginx_v15ping不通net-test網路的nginx_v14
#但是net-test網路的nginx_v14可以ping通預設Bridge網路的nginx_v15

image-20240603085937703

docker network disconnect bridge nginx_v14
#斷開nginx_v14容器與Bridge網路模式中的其他容器通訊
#現在兩個不同網路的容器無法通訊

image-20240603090405755

相關文章