開始理解 docker
一開始,我們們思考一下,宿主機怎麼和容器通訊呢?
說容器之間是相互隔離的,那麼他們是否可以通訊?又是如何通訊的呢?
開始探索
我們先來看看我們環境中的映象都有些啥,有 xmtubuntu
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xmtubuntu latest c3e95388a66b 38 seconds ago 114MB
再來看看宿主機的網路卡資訊
ip addr
來檢視我們們宿主機的網路卡資訊
我們發現有一個docker0
,是因為我們的宿主機上面安裝了docker 的服務,docker 會給我生成一個虛擬網路卡,圖中的這個 docker0
就是虛擬網路卡資訊
建立並啟動一個docker 命名為 ubuntu1
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
ubuntu1
pingdocker0
,同樣的 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
在此處就是充當了一個橋樑,連線各種虛擬裝置
通過上圖我們可以得出如下結論:
ubuntu1
和ubuntu2
他們是公用一個路由器,也就是 docker0,ubuntu1 能ping通ubuntu2
是因為 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.254
, 192.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
可以使用 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/mypic/raw/ master/image-20210807204514806.png)
現在,要跨網路操作別人的容器,我們就可以使用 docker network connect
的方式將網路打通,開始幹活了
大家對網路還感興趣嗎,哈哈,關於 docker 的前幾期文章連結如下,可以逐步學習,慢慢深入,多多回顧
【Docker 系列】docker 學習 五,我們來看看容器資料捲到底是個啥
【Docker 系列】docker 學習 四,一起學習映象相關原理
【Docker 系列】docker 學習 三,docker 初步實戰和 docker 視覺化管理工具試煉
【Docker 系列】docker 學習 二,docker 常用命令,映象命令,容器命令,其他命令
【Docker 系列】docker 學習 一,Docker的安裝使用及Docker的基本工作原理 | 8月更文挑戰
參考資料:
歡迎點贊,關注,收藏
朋友們,你的支援和鼓勵,是我堅持分享,提高質量的動力
好了,本次就到這裡
技術是開放的,我們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是小魔童哪吒,歡迎點贊關注收藏,下次見~
本作品採用《CC 協議》,轉載必須註明作者和本文連結