這是我參與8月更文挑戰的第10天,活動詳情查看:8月更文挑戰git
一開始,我們思考一下,宿主機怎麼和容器通訊呢?redis
說容器之間是相互隔離的,那麼他們是否能夠通訊?又是如何通訊的呢?mongodb
咱們先來看看咱環境中的鏡像都有些啥,有 xmtubuntu
docker
# 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
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 幫助其轉發的那麼經過上圖咱們就知道,容器和宿主機以前是經過橋接的方式來打通網絡的。
Dcoker 中全部的網絡接口都是虛擬的,由於虛擬的轉發效率高呀,當咱們刪除某一個容器的時候,這個容器對應的網卡信息,也會被隨之刪除掉
那麼咱們能夠思考一下,若是都是經過找ip
地址來通訊,若是 ip
變化了,那麼咱們豈不是找不到正確的容器了嗎?咱們是否能夠經過服務名來訪問容器呢?
固然是能夠的,當咱們在建立和啓動容器的時候加上–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
複製代碼
網絡模式
橋接,docker0 默認使用 bridge 這個名字
和宿主機共享網絡
不配置網絡
容器網絡連通,這個模式用的很是少,由於侷限性很大
如今我們能夠自定義個網絡,來連通兩個容器
自定義一個 mynet 網絡
# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
9a597fc31f1964d434181907e21ff7010738f3f7dc35ba86bf7434f05a6afc4a
複製代碼
建立一個網絡
指定驅動是 bridge
指定子網
指定網關
此處咱們設置子網是 --subnet 192.168.0.0/16
,網關是192.168.0.1
,那麼咱們剩下可使用的ip
就是 192.168.0.2 – 192.168.255.254
, 192.168.255.255
是廣播地址
清空全部測試的容器,減去幹擾
# 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

如今,要跨網絡操做別人的容器,咱們就可使用 docker network connect
的方式將網絡打通,開始幹活了
你們對網絡還感興趣嗎,哈哈,關於 docker 的前幾期文章連接以下,能夠逐步學習,慢慢深刻,多多回顧
【Docker 系列】docker 學習 五,咱們來看看容器數據卷究竟是個啥
【Docker 系列】docker 學習 四,一塊兒學習鏡像相關原理
【Docker 系列】docker 學習 三,docker 初步實戰和 docker 可視化管理工具試煉
【Docker 系列】docker 學習 二,docker 經常使用命令,鏡像命令,容器命令,其餘命令
【Docker 系列】docker 學習 一,Docker的安裝使用及Docker的基本工做原理 | 8月更文挑戰
參考資料:
朋友們,你的支持和鼓勵,是我堅持分享,提升質量的動力
好了,本次就到這裏
技術是開放的,咱們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
我是小魔童哪吒,歡迎點贊關注收藏,下次見~