【Docker 系列】docker 學習八,有趣的 Docker 網絡

這是我參與8月更文挑戰的第10天,活動詳情查看:8月更文挑戰git

【Docker 系列】docker 學習八,Docker 網絡

開始理解 docker

一開始,我們思考一下,宿主機怎麼和容器通訊呢?redis

說容器之間是相互隔離的,那麼他們是否能夠通訊?又是如何通訊的呢?mongodb

開始探索

咱們先來看看咱環境中的鏡像都有些啥,有 xmtubuntudocker

# docker images
REPOSITORY            TAG       IMAGE ID       CREATED          SIZE
xmtubuntu             latest    c3e95388a66b   38 seconds ago   114MB
複製代碼

再來看看宿主機的網卡信息shell

ip addr 來查看我們宿主機的網卡信息ubuntu

咱們發現有一個 docker0,是由於咱們的宿主機上面安裝了docker 的服務,docker 會給我生成一個虛擬網卡,圖中的這個 docker0就是虛擬網卡信息bash

建立並啓動一個docker 命名爲 ubuntu1markdown

docker run -it --name ubuntu1 -P xmtubuntu網絡

查看一下宿主機網卡信息工具

查看宿主機的網卡信息

再查看 ubuntu1 的網卡信息,docker 也會默認給咱們的容器分配ip 地址

能夠發現宿主機的網卡信息 docker0 下面多了117: veth838e165@if116:ubuntu1的網卡信息上也正好有116: eth0@if117

咱們發現這些veth的編號是成對出現的,我們的宿主機就能夠和 ubuntu1 進行通訊了

使用宿主機(docker0)和ubuntu1互相 ping

docker0 pingubuntu1 ok

ubuntu1pingdocker0 ,一樣的 ok

我們能夠嘗試再建立並啓動一個docker 命名爲 ubuntu2,方法和上述徹底一致

# docker run -it -P --name ubuntu2 xmtubuntu
複製代碼

進入容器,使用ip a查看到ubuntu2的網卡信息

宿主機上面查看網信息

宿主機上面又多了一個 veth , 119: veth0b29558@if118

ubuntu2上的網卡信息是118: eth0@if119,他們一樣是成對出現的,小夥伴看到這裏應該明白了吧

ubuntu1 ping ubuntu2 呢?

ubuntu1 對應 172.18.0.2

ubuntu2 對應 172.18.0.3

# docker exec -it ubuntu1 ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.071 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from 172.18.0.3: icmp_seq=3 ttl=64 time=0.077 ms
複製代碼

仍然是能夠通訊,很是 nice

原理是什麼?

上述的探索,咱們發現宿主機建立的容器,均可以直接ping通宿主機,那麼他們的原理是啥呢?

細心的 xdm 應該能夠看出來,上述的例子中,veth是成對出現的,上述宿主機和容器可以進行網絡通訊,得益於這個技術veth-pair

veth-pair

**veth-pair **是一對虛擬設備接口,他們都是成對出現的,一段連着協議,一段彼此相連

正是由於這個特性,veth-pair在此處就是充當了一個橋樑,鏈接各類虛擬設備

經過上圖咱們能夠得出以下結論:

  • ubuntu1ubuntu2他們是公用一個路由器,也就是 docker0,ubuntu1 能pingubuntu2是由於 docker0 幫助其轉發的
  • 全部的容器在不指定路由的狀況下,都是以 docker0 做爲路由,docker 也會給咱們的容器分配一個可用的 ip
  • docker0 是在宿主機上面安裝 docker 服務就會存在的

那麼經過上圖咱們就知道,容器和宿主機以前是經過橋接的方式來打通網絡的。

Dcoker 中全部的網絡接口都是虛擬的,由於虛擬的轉發效率高呀,當咱們刪除某一個容器的時候,這個容器對應的網卡信息,也會被隨之刪除掉

那麼咱們能夠思考一下,若是都是經過找ip地址來通訊,若是 ip變化了,那麼咱們豈不是找不到正確的容器了嗎?咱們是否能夠經過服務名來訪問容器呢?

–link

固然是能夠的,當咱們在建立和啓動容器的時候加上–link就能夠達到這個效果

咱們再建立一個容器 ubuntu3,讓他 link 到 ubuntu2

# docker run -it --name ubuntu3 -P --link ubuntu2 xmtubuntu

# docker exec -it ubuntu3 ping ubuntu2
PING ubuntu2 (172.18.0.3) 56(84) bytes of data.
64 bytes from ubuntu2 (172.18.0.3): icmp_seq=1 ttl=64 time=0.093 ms
64 bytes from ubuntu2 (172.18.0.3): icmp_seq=2 ttl=64 time=0.085 ms
64 bytes from ubuntu2 (172.18.0.3): icmp_seq=3 ttl=64 time=0.092 ms
64 bytes from ubuntu2 (172.18.0.3): icmp_seq=4 ttl=64 time=0.073 ms
複製代碼

很明顯,咱們能夠到看到 ubuntu3 能夠經過服務名ubuntu2 直接和ubuntu2通訊,可是反過來是否能夠呢?

# docker exec -it ubuntu2 ping ubuntu3
ping: ubuntu3: Name or service not known
複製代碼

不行?這是爲何呢?

咱們來查看一下 ubuntu3 的本地 /etc/hosts 文件就清楚了

看到這裏,這就清楚了 link 的原理了吧,就是在本身的 /etc/hosts 文件中,加入一個host而已,這個知識點咱們能夠都知悉一下,可是這個 link 仍是好搓,很差,他須要在建立和啓動容器的時候使用,用起來不方便

那麼咱們有沒有更好的辦法的呢?

自定義網絡

可使用 docker network ls查看宿主機 docker 的網絡狀況

:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
8317183dfc58   bridge    bridge    local
997107487c6b   host      host      local
ab130876cbe6   none      null      local
複製代碼

網絡模式

  • bridge

橋接,docker0 默認使用 bridge 這個名字

  • host

和宿主機共享網絡

  • none

不配置網絡

  • container

容器網絡連通,這個模式用的很是少,由於侷限性很大

如今我們能夠自定義個網絡,來連通兩個容器

自定義網絡

自定義一個 mynet 網絡

# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
9a597fc31f1964d434181907e21ff7010738f3f7dc35ba86bf7434f05a6afc4a
複製代碼
  • docker network create

建立一個網絡

  • --driver

指定驅動是 bridge

  • --subnet

指定子網

  • --gateway

指定網關

此處咱們設置子網是 --subnet 192.168.0.0/16,網關是192.168.0.1,那麼咱們剩下可使用的ip就是 192.168.0.2 – 192.168.255.254192.168.255.255是廣播地址

清空已有的容器

清空全部測試的容器,減去幹擾

建立並啓動2個容器,分別是ubuntu1 和 ubuntu2

# docker run -it -P --name ubuntu1 --net mynet xmtubuntu
# docker run -it -P --name ubuntu2 --net mynet xmtubuntu
複製代碼

此時咱們能夠查看一下宿主機的網卡信息,並驗證兩個容器直接經過容器名字是否能夠通訊

咱們思考一下自定義網絡的好處

我們自定義 docker 網絡,已經幫咱們維護好了對應關係,這樣作的好處是容器之間能夠作到網絡隔離,

例如

一堆 redis 的容器,使用 192.168.0.0/16 網段,網關是 192.168.0.1

一堆 mongodb的容器,使用 192.167.0.0/16 網段,網關是 192.167.0.1

這樣就能夠作到子網很好的隔離開來,不一樣的集羣使用不一樣的子網,互不影響

那麼子網間是否能夠打通呢?

網絡連通

兩個不一樣子網內的容器如何連通了呢?

咱們絕對不可能讓不一樣子網的容器不經過路由的轉發而直接通訊,這是不可能的,子網之間是相互隔離的

可是咱們有辦法讓 ubuntu3 這個容器經過和 mynet 打通,進而轉發到 ubuntu1 或者 ubuntu2 中就能夠了

打通子網

咱們查看 docker network 的幫助手冊

docker network -h

image-20210807203841520

可使用 docker network connect 命令實現,在查看一下幫助文檔

# docker network connect -h
Flag shorthand -h has been deprecated, please use --help

Usage:  docker network connect [OPTIONS] NETWORK CONTAINER

Connect a container to a network
複製代碼

開始打通

docker network connect mynet ubuntu3

這個時候咱們能夠查看一下 mynet 網絡的詳情

# docker network inspect mynet
複製代碼

能夠看到在 mynet 網絡上,又增長了一個容器,ip 是 192.168.0.4

沒錯,docker 處理這種網絡打通的事情就是這麼簡單粗暴,直接在 ubuntu3 容器上增長一個虛擬網卡,讓 ubuntu3 可以和 mynet 網絡打通

宿主機固然也相應的多了一個veth

![](gitee.com/common_dev/… master/image-20210807204514806.png)

如今,要跨網絡操做別人的容器,咱們就可使用 docker network connect的方式將網絡打通,開始幹活了

你們對網絡還感興趣嗎,哈哈,關於 docker 的前幾期文章連接以下,能夠逐步學習,慢慢深刻,多多回顧

【Docker 系列】docker 學習 五,咱們來看看容器數據卷究竟是個啥

【Docker 系列】docker 學習 四,一塊兒學習鏡像相關原理

【Docker 系列】docker 學習 三,docker 初步實戰和 docker 可視化管理工具試煉

【Docker 系列】docker 學習 二,docker 經常使用命令,鏡像命令,容器命令,其餘命令

【Docker 系列】docker 學習 一,Docker的安裝使用及Docker的基本工做原理 | 8月更文挑戰

參考資料:

docker docs

歡迎點贊,關注,收藏

朋友們,你的支持和鼓勵,是我堅持分享,提升質量的動力

好了,本次就到這裏

技術是開放的,咱們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。

我是小魔童哪吒,歡迎點贊關注收藏,下次見~

相關文章
相關標籤/搜索