摘要:而本文主要針對(duì)容器間的網(wǎng)絡(luò)通信方法進(jìn)行討論。而同屬于用戶自定義的容器之間自動(dòng)將所有端口暴露,方便容器間進(jìn)行無障礙的通信,而不會(huì)遭受到外界的意外訪問。
幾天前,為了解決日常在本地進(jìn)行日常工作和開發(fā)測(cè)試之間的矛盾,利用docker在Windows系統(tǒng)中搭建了基于Linux的測(cè)試環(huán)境:借助Docker,在win10下編碼,一鍵在Linux下測(cè)試。在這邊文章里主要介紹了如何在本地通過docker構(gòu)建與生產(chǎn)環(huán)境基本一致的環(huán)境并一鍵運(yùn)行、測(cè)試我們的代碼。Docker官方建議每個(gè)容器中只運(yùn)行一個(gè)服務(wù)[1],但是我們的項(xiàng)目可能是由多個(gè)服務(wù)組成,在服務(wù)中可能會(huì)需要mysql、redis等中間件的支持,所以通常我們將一個(gè)項(xiàng)目的不同服務(wù)劃分到不同容器中。這種做法雖然具有低耦合、高隔離性等優(yōu)點(diǎn),但是也增加了服務(wù)之間通信的復(fù)雜度。
Docker容器間的通信方式根據(jù)媒介可以分為:volume共享通信、網(wǎng)絡(luò)通信等;根據(jù)通信范圍也可以分為:同主機(jī)通信和跨主機(jī)通信等。而本文主要針對(duì)容器間的網(wǎng)絡(luò)通信方法進(jìn)行討論。
1. Docker的網(wǎng)絡(luò)驅(qū)動(dòng)模型
Docker的網(wǎng)絡(luò)驅(qū)動(dòng)模型分類:
bridge:Docker中默認(rèn)的網(wǎng)絡(luò)驅(qū)動(dòng)模型,在啟動(dòng)容器時(shí)如果不指定則默認(rèn)為此驅(qū)動(dòng)類型;
host:打破Docker容器與宿主機(jī)之間的網(wǎng)絡(luò)隔離,直接使用宿主機(jī)的網(wǎng)絡(luò)環(huán)境,該模型僅適用于Docker17.6及以上版本;
overlay:可以連接多個(gè)docker守護(hù)進(jìn)程或者滿足集群服務(wù)之間的通信;適用于不同宿主機(jī)上的docker容器之間的通信;
macvlan:可以為docker容器分配MAC地址,使其像真實(shí)的物理機(jī)一樣運(yùn)行;
none:即禁用了網(wǎng)絡(luò)驅(qū)動(dòng),需要自己手動(dòng)自定義網(wǎng)絡(luò)驅(qū)動(dòng)配置;
plugins:使用第三方網(wǎng)絡(luò)驅(qū)動(dòng)插件;
以上是Docker支持的幾種網(wǎng)絡(luò)驅(qū)動(dòng)模型,它們都具有獨(dú)特的特點(diǎn)和應(yīng)用范圍,為了更加詳細(xì)地了解Docker的網(wǎng)絡(luò)運(yùn)行原理,下面挑選幾種較為重要的網(wǎng)絡(luò)模型進(jìn)行研究。
2. bridge
如上圖所示為Docker中bridge驅(qū)動(dòng)模式的示意圖,其中藍(lán)色的模塊表示主機(jī)上的網(wǎng)卡。當(dāng)Docker啟動(dòng)時(shí)會(huì)自動(dòng)在主機(jī)上創(chuàng)建一個(gè)虛擬網(wǎng)橋docker0,使用默認(rèn)網(wǎng)絡(luò)模式創(chuàng)建docker容器時(shí)會(huì)自動(dòng)創(chuàng)建一對(duì)兒veth pair接口,一端連接在docker容器中(如圖容器中的eth0),一端連接在虛擬網(wǎng)橋docker0上(如圖veth)。這種veth pair是一種虛擬網(wǎng)絡(luò)設(shè)備,主要用于不同namespace中(意味著網(wǎng)絡(luò)隔離)的網(wǎng)絡(luò)通信,它總是成對(duì)存在的。在這里可以把它想象成一對(duì)兒靠虛擬網(wǎng)線連接起來的兩個(gè)虛擬網(wǎng)卡,一端連接著docker容器,一端連接著虛擬網(wǎng)橋docker0。
通過這種方式,不同docker容器之間可以通過ip地址互相通信,也可以通過虛擬網(wǎng)橋訪問主機(jī)上的網(wǎng)絡(luò)eth0(添加iptables規(guī)則,將docker容器對(duì)目標(biāo)地址發(fā)出的訪問通過地址偽裝的方式修改為主機(jī)對(duì)目標(biāo)地址進(jìn)行訪問)。
如果想要外界網(wǎng)絡(luò)訪問docker容器時(shí),需要在docker容器啟動(dòng)時(shí)加上參數(shù)"-p [主機(jī)端口]:[容器端口]"進(jìn)行端口映射,原理也是通過修改iptables規(guī)則將訪問[主機(jī)端口]的數(shù)據(jù)轉(zhuǎn)發(fā)到docker容器的[容器端口]中,但是這種做法也存在著占用主機(jī)有限的端口資源的缺點(diǎn)。
在主機(jī)上通過命令docker network ls可以查看docker中存在的網(wǎng)絡(luò):
docker network ls
# 輸出結(jié)果:
NETWORK ID NAME DRIVER SCOPE
e79b7548b225 bridge bridge local
666d5f1f459d host host local
d0d785cf4794 none null local
然后通過命令docker network inspect bridge查看bridge網(wǎng)絡(luò)的詳細(xì)配置:
docker network inspect bridge
# 輸出結(jié)果:
[
{
"Name": "bridge",
"Id": "e79b7548b225c3c80d0f70d0de0b5911ed70a7f39ac20f75a8ae71c5cef05b3a",
"Created": "2019-05-17T13:01:27.6581642Z",
"Scope": "local",
"Driver": "bridge", # bridge驅(qū)動(dòng)模式
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16", # 子網(wǎng),docker容器的IP范圍
"Gateway": "172.17.0.1" # 網(wǎng)關(guān),即docker0
}
]
},
...
省略
...
# 兩個(gè)docker容器(一個(gè)mysql容器,一個(gè)Web服務(wù)容器)的網(wǎng)絡(luò)配置
"Containers": {
# mysql容器
"d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679": {
"Name": "mysqld5.7",
"EndpointID": "32e900f33367e3570c416c43a5618bd7a742cf94f36799e92895951ed1784736",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16", # 容器的IP
"IPv6Address": ""
},
# 基于tornado的Web服務(wù)容器
"dd292d535d16bbfe5382e29486756f4ffffdfea8e9b10af769db61618d739c5c4e": {
"Name": "test_demo",
"EndpointID": "eaf8e294f7b54aa50c6e6b30ac91f63b1a0ccbc5b56d6fbdcfeacd0471b15eb3",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16", # 容器的IP
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
由上述配置信息可以看出,docker網(wǎng)橋的網(wǎng)關(guān)的IP為"172.17.0.1",也即docker0,而docker的子網(wǎng)為"172.17.0.0/16",docker將會(huì)為容器在"172.17.0.0/16"中分配IP,如其中的mysql容器的IP為"172.17.0.2/16"、test_demo容器的IP為"172.17.0.3/16"。由于不同容器通過veth pair連接在虛擬網(wǎng)橋docker0上,所以容器之間可以通過IP互相通信,但是無法通過容器名進(jìn)行通信:
# 在test_demo容器中訪問mysqld5.7容器(通過IP)
ping 172.17.0.2 -c 3
# 輸出結(jié)果:
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.147 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.185 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.209 ms
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2057ms
rtt min/avg/max/mdev = 0.147/0.180/0.209/0.027 ms
# 在test_demo容器中訪問mysqld5.7容器(通過容器名)
ping mysqld5.7
# 輸出結(jié)果:
ping: mysqld5.7: Name or service not known
所以,默認(rèn)的網(wǎng)橋bridge上的容器只能通過IP互連,無法通過DNS解析名稱或別名。假如我們?cè)赾ontainer1中部署了Web服務(wù),在container2中部署了mysql,container1中的Web服務(wù)往往需要連接container2的mysql,這是只能靠IP進(jìn)行連接,但是docker也無法保證容器重啟后的IP地址不變,所以更好的方式是通過別名進(jìn)行互聯(lián),在網(wǎng)絡(luò)中加入DNS服務(wù)器,將容器名與IP地址進(jìn)行匹配,省去了手動(dòng)修改Web服務(wù)中連接mysql的IP的過程。
為了實(shí)現(xiàn)不同容器通過容器名或別名的互連,docker提供了以下幾種:
在啟動(dòng)docker容器時(shí)加入--link參數(shù),但是目前已經(jīng)被廢棄,廢棄的主要原因是需要在連接的兩個(gè)容器上都創(chuàng)建--link選項(xiàng),當(dāng)互連的容器數(shù)量較多時(shí),操作的復(fù)雜度會(huì)顯著增加;
啟動(dòng)docker容器后進(jìn)入容器并修改/etc/host配置文件,缺點(diǎn)是手動(dòng)配置較為繁雜;
用戶自定義bridge網(wǎng)橋,這是目前解決此類問題的主要方法;
用戶自定義bridge相對(duì)于使用默認(rèn)bridge的主要優(yōu)勢(shì):
用戶自定義bridge可以在容器化的應(yīng)用程序提供更好的隔離效果和更好的互通性: 這段話看似有些矛盾,但是其中更好的隔離效果是針對(duì)外界網(wǎng)絡(luò),而更好的互通性則是指同一bridge下的不同容器之間。還是以之前的分別部署了Web服務(wù)和mysql服務(wù)的兩個(gè)容器container1、container2為例,container1只需要對(duì)外界網(wǎng)絡(luò)暴露Web服務(wù)的80端口,而負(fù)責(zé)后端的container2只需與container1互連,不需要對(duì)外暴露,有效地保護(hù)了后端容器的安全性,提高了容器對(duì)外的隔離效果。而同屬于用戶自定義bridge的容器container1、container2之間自動(dòng)將所有端口暴露,方便容器間進(jìn)行無障礙的通信,而不會(huì)遭受到外界的意外訪問。
用戶自定義bridge在容器之間提供了自動(dòng)DNS解析: 這也是本文討論的重點(diǎn),不同于默認(rèn)bridge只能通過IP互連的限制,用戶自定義的bridge自動(dòng)提供了容器間的DNS解析功能,容器間可以通過容器名或別名進(jìn)行通信。
創(chuàng)建用戶自定義bridge:
docker network create my-net # 創(chuàng)建了一個(gè)名為"my-net"的網(wǎng)絡(luò)
將Web服務(wù)容器和mysql服務(wù)容器加入到"my-net"中,并觀察變化:
docker network connect my-net test_demo # 將Web服務(wù)加入my-net網(wǎng)絡(luò)中 docker network connect my-net mysqld5.7 # 將mysql服務(wù)加入my-net網(wǎng)絡(luò)中
# 查看my-net的網(wǎng)絡(luò)配置
docker network inspect my-net
# 輸出結(jié)果(省略部分內(nèi)容):
[
{
"Name": "my-net",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Config": [
{
"Subnet": "172.18.0.0/16", # my-net的子網(wǎng)
"Gateway": "172.18.0.1" # my-net的網(wǎng)關(guān)
}
]
},
"Containers": {
"d6f33e9bbd60e10d02dd2eebea424a7fc129d9646c96742ec3fe467833017679": {
"Name": "mysqld5.7",
"EndpointID": "7d0e8d70bb523cceb4d2d8d4e3f8231fc68332c70f7f9b4e5d4abccce2b31a65",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16", # mysql服務(wù)容器的IP,與之前不同
"IPv6Address": ""
},
"dd292d535d16bbfe5382e29486756f4ffffdfea8e9b10af769db61618d739c5c4e": {
"Name": "test_demo",
"EndpointID": "f7802f1af81e258f77e227609dfdcdf66c49f19776381eb8b0dca6d9e794ccad",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16", # Web服務(wù)容器的IP,與之前不同
"IPv6Address": ""
}
},
}
]
如上所示,用戶自定義網(wǎng)絡(luò)my-net的子網(wǎng)為"172.18.0.0/16",所以兩docker容器在my-net網(wǎng)絡(luò)中的IP分別為:"172.18.0.3/16"、"172.18.0.2/16",與之前的"172.17.0.2/16"、"172.17.0.3/16"不同。
通過容器名或別名互連: 進(jìn)入到Web服務(wù)器container1中連接container2:
ping mysqld5.7 -c 3
# 輸出結(jié)果:
PING mysqld5.7 (172.18.0.3) 56(84) bytes of data.
64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.145 ms
64 bytes from mysqld5.7.my-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.143 ms
--- mysqld5.7 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2048ms
rtt min/avg/max/mdev = 0.066/0.118/0.145/0.036 ms
如上所示,我們已經(jīng)可以通過容器名"mysqld5.7"連接mysql服務(wù)器了。
斷開網(wǎng)絡(luò): 由于我們的容器仍然連接著默認(rèn)bridgedocker0,而現(xiàn)在我們已經(jīng)不需要它,所以應(yīng)該將容器與docker0的連接斷開,執(zhí)行以下操作:
# 斷開容器與docker0的連接
docker network disconnect bridge test_demo
docker network disconnect bridge mysqld5.7
3. overlay
關(guān)鍵字:跨主機(jī)通信、集群
Run multiple services in a container. docs.docker.com/config/cont… ??
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/6726.html
摘要:各項(xiàng)配置如下主機(jī)的地址為主機(jī)的地址為為主機(jī)上的容器分配的子網(wǎng)為主機(jī)上的容器分配的子網(wǎng)這樣配置之后,兩個(gè)主機(jī)上的容器就肯定不會(huì)使用相同的地址從而避免了沖突。 showImg(https://segmentfault.com/img/remote/1460000015283239); 概述 就目前Docker自身默認(rèn)的網(wǎng)絡(luò)來說,單臺(tái)主機(jī)上的不同Docker容器可以借助docker0網(wǎng)橋...
摘要:是容器中的一條,是由參數(shù)添加進(jìn)來的。補(bǔ)充容器重啟后可能變化,所以直接在中指定并不是一個(gè)好方法。使用時(shí)文件會(huì)隨著容器的變化更新,所以使用域名才是更容易維護(hù)的方法。 轉(zhuǎn)載請(qǐng)注明出處,原文鏈接http://tailnode.tk/2017/01/do... 以我的ghost博客為例進(jìn)行說明,我在VPS上用docker啟動(dòng)了兩個(gè)ghost博客,還有一個(gè)Nginx做反向代理,將兩個(gè)域名分別指向兩...
摘要:本文涵蓋了中的六大新特性內(nèi)置命令服務(wù)發(fā)現(xiàn)自愈功能安全負(fù)載均衡滾動(dòng)升級(jí),相關(guān)的使用文檔和視頻鏈接也都包含在里面。同時(shí),內(nèi)部負(fù)載均衡要求一個(gè)可用的容器?,F(xiàn)在開箱即用的負(fù)載均衡,上公開暴露的端口在所有節(jié)點(diǎn)都是可以訪問的。 Docker 1.12版本最近剛剛發(fā)布,這篇文章對(duì)它的新特性進(jìn)行了概述和對(duì)比描述。本文涵蓋了 Docker 1.12 中的六大新特性:內(nèi)置 swarm命令、服務(wù)發(fā)現(xiàn)、自愈功...
摘要:日志會(huì)顯示令牌過期的信息,隨后檢查主機(jī)和主機(jī)的時(shí)鐘是否同步。如果這個(gè)子網(wǎng)已經(jīng)被使用,你將需要更改網(wǎng)絡(luò)中使用的默認(rèn)子網(wǎng)。如果負(fù)載均衡器處于初始化狀態(tài),則很可能主機(jī)之間無法進(jìn)行跨主機(jī)通信。而一直顯示黃色初始化狀態(tài),說明一直沒有通過健康檢查。 一、服務(wù)/容器 1、為什么我只能編輯容器的名稱? Docker容器在創(chuàng)建之后就不可更改了。唯一可更改的內(nèi)容是我們要存儲(chǔ)的不屬于Docker容器本身的那...
閱讀 4186·2021-11-22 13:52
閱讀 2094·2021-09-22 15:12
閱讀 1133·2019-08-30 15:53
閱讀 3467·2019-08-29 17:12
閱讀 2198·2019-08-29 16:23
閱讀 1662·2019-08-26 13:56
閱讀 1778·2019-08-26 13:44
閱讀 1897·2019-08-26 11:56