十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶(hù) + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專(zhuān)業(yè)推廣+無(wú)憂(yōu)售后,網(wǎng)站問(wèn)題一站解決
這篇“Docker容器怎么通過(guò)獨(dú)立IP暴露給局域網(wǎng)”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Docker容器怎么通過(guò)獨(dú)立IP暴露給局域網(wǎng)”文章吧。
創(chuàng)新互聯(lián)公司2013年成立,先為郊區(qū)等服務(wù)建站,郊區(qū)等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為郊區(qū)企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
docker容器非常輕量,系統(tǒng)開(kāi)銷(xiāo)非常少,比vmware或者virtualbox用起來(lái)方便,部署起來(lái)也非常容易。官方推薦我們通過(guò)端口映射的方式把docker容器的服務(wù)提供給宿主機(jī)或者局域網(wǎng)其他容器使用。一般過(guò)程是:
1、docker進(jìn)程通過(guò)監(jiān)聽(tīng)宿主機(jī)的某個(gè)端口,將該端口的數(shù)據(jù)包發(fā)送給docker容器
2、宿主機(jī)可以打開(kāi)防火墻讓局域網(wǎng)其他設(shè)備通過(guò)訪(fǎng)問(wèn)宿主機(jī)的端口進(jìn)而訪(fǎng)問(wèn)docker的端口
這里以cDNS為例,cdns是一個(gè)用于避免dns污染的程序,通過(guò)cdns可以把你的計(jì)算機(jī)變成一個(gè)抗污染的dns服務(wù)器提供給局域網(wǎng)使用。docker鏡像下載地址:
原理是在docker容器中啟動(dòng)cdns,監(jiān)聽(tīng)53端口,docker容器的ip地址為172.12.0.2,宿主機(jī)把5053端口映射到docker容器上,訪(fǎng)問(wèn)宿主機(jī)的127.0.0.1:5053就相當(dāng)于訪(fǎng)問(wèn)docker的53端口,所以docker的啟動(dòng)方法是:
sudo docker run -itd -p 0.0.0.0:5053:53/udp --name=curedns alexzhuo/cdns cdns -c /etc/cdns.config.json
這樣我們使用dig工具通過(guò)5053端口查詢(xún)dns就是無(wú)污染的dns了,過(guò)程如下:
alex@alex-lenovo-u310:~$ dig www.facebook.com @127.0.0.1 -p 5053 ; <<>> dig 9.10.3-p4-ubuntu <<>> www.facebook.com @127.0.0.1 -p 5053 ;; global options: +cmd ;; got answer: ;; ->>header<<- opcode: query, status: noerror, id: 9522 ;; flags: qr rd ra; query: 1, answer: 2, authority: 2, additional: 5 ;; opt pseudosection: ; edns: version: 0, flags:; udp: 4096 ;; question section: ;www.facebook.com. in a ;; answer section: www.facebook.com. 1550 in cname star-mini.c10r.facebook.com. star-mini.c10r.facebook.com. 30 in a 31.13.95.36 ;; authority section: c10r.facebook.com. 2010 in ns a.ns.c10r.facebook.com. c10r.facebook.com. 2010 in ns b.ns.c10r.facebook.com. ;; additional section: a.ns.c10r.facebook.com. 2439 in a 69.171.239.11 a.ns.c10r.facebook.com. 2439 in aaaa 2a03:2880:fffe:b:face:b00c:0:99 b.ns.c10r.facebook.com. 3351 in a 69.171.255.11 b.ns.c10r.facebook.com. 1253 in aaaa 2a03:2880:ffff:b:face:b00c:0:99 ;; query time: 47 msec ;; server: 127.0.0.1#5053(127.0.0.1) ;; when: mon apr 10 16:21:46 cst 2017 ;; msg size rcvd: 213
這里假設(shè)我們的宿主機(jī)ip是192.168.12.107
如果現(xiàn)在出現(xiàn)另外一臺(tái)局域網(wǎng)計(jì)算機(jī),ip地址為192.168.12.113,它想把宿主機(jī)當(dāng)成dns服務(wù)器,那么我們就需要在192.168.12.113這臺(tái)計(jì)算機(jī)上訪(fǎng)問(wèn)192.168.12.107:5053來(lái)查詢(xún)dns,dig命令如下
dig www.facebook.com @192.168.12.107 -p 5053
這樣做顯然是很不方便的,我們現(xiàn)在希望不經(jīng)過(guò)宿主機(jī)這一套nat和代理,想要直接在局域網(wǎng)內(nèi)的任意一臺(tái)計(jì)算機(jī)上直接通過(guò)ip訪(fǎng)問(wèn)docker容器,讓docker容器完整的暴露在局域網(wǎng)里而不是僅單單暴露一個(gè)53端口。那么應(yīng)該如何做呢?
首先通過(guò)觀(guān)察發(fā)現(xiàn),docker的默認(rèn)啟動(dòng)方式中,會(huì)產(chǎn)生一塊虛擬網(wǎng)卡,在這里我們可以理解這塊網(wǎng)卡連接著一個(gè)虛擬交換機(jī),然后每個(gè)docker容器又會(huì)擁有自己?jiǎn)为?dú)的網(wǎng)卡和ip,而且所有docker容器也連接在這個(gè)虛擬交換機(jī)的下面。我們可以在宿主機(jī)上通過(guò)ifconfig命令看到這個(gè)虛擬網(wǎng)卡。
alex@alex-lenovo-u310:~$ ifconfig docker0 link encap:以太網(wǎng) 硬件地址 02:42:cd:21:5c:81 inet 地址:172.17.0.1 廣播:0.0.0.0 掩碼:255.255.0.0 inet6 地址: fe80::42:cdff:fe21:5c81/64 scope:link up broadcast running multicast mtu:1500 躍點(diǎn)數(shù):1 接收數(shù)據(jù)包:2892 錯(cuò)誤:0 丟棄:0 過(guò)載:0 幀數(shù):0 發(fā)送數(shù)據(jù)包:3517 錯(cuò)誤:0 丟棄:0 過(guò)載:0 載波:0 碰撞:0 發(fā)送隊(duì)列長(zhǎng)度:0 接收字節(jié):187022 (187.0 kb) 發(fā)送字節(jié):4771886 (4.7 mb) lo link encap:本地環(huán)回 inet 地址:127.0.0.1 掩碼:255.0.0.0 inet6 地址: ::1/128 scope:host up loopback running mtu:65536 躍點(diǎn)數(shù):1 接收數(shù)據(jù)包:9993 錯(cuò)誤:0 丟棄:0 過(guò)載:0 幀數(shù):0 發(fā)送數(shù)據(jù)包:9993 錯(cuò)誤:0 丟棄:0 過(guò)載:0 載波:0 碰撞:0 發(fā)送隊(duì)列長(zhǎng)度:1 接收字節(jié):934304 (934.3 kb) 發(fā)送字節(jié):934304 (934.3 kb) wlp3s0 link encap:以太網(wǎng) 硬件地址 74:e5:43:b0:dd:b0 inet 地址:192.168.12.107 廣播:192.168.12.255 掩碼:255.255.255.0 inet6 地址: fe80::8adf:28f7:5ec:3a5d/64 scope:link up broadcast running multicast mtu:1500 躍點(diǎn)數(shù):1 接收數(shù)據(jù)包:69760 錯(cuò)誤:0 丟棄:0 過(guò)載:0 幀數(shù):0 發(fā)送數(shù)據(jù)包:64718 錯(cuò)誤:0 丟棄:0 過(guò)載:0 載波:0 碰撞:0 發(fā)送隊(duì)列長(zhǎng)度:1000 接收字節(jié):41517057 (41.5 mb) 發(fā)送字節(jié):9971762 (9.9 mb)
上面的docker0這塊網(wǎng)卡就是虛擬網(wǎng)卡,它的ip地址是172.17.0.1,它和其他的docker容器都連接在一個(gè)虛擬交換機(jī)上,網(wǎng)段為172.17.0.0/16,下面我們登錄到docker容器里面,查看一下容器的網(wǎng)卡和ip
# ifconfig eth0 link encap:ethernet hwaddr 02:42:ac:11:00:02 inet addr:172.17.0.2 bcast:0.0.0.0 mask:255.255.0.0 inet6 addr: fe80::42:acff:fe11:2/64 scope:link up broadcast running multicast mtu:1500 metric:1 rx packets:3449 errors:0 dropped:0 overruns:0 frame:0 tx packets:2811 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 rx bytes:4763490 (4.7 mb) tx bytes:219998 (219.9 kb) lo link encap:local loopback inet addr:127.0.0.1 mask:255.0.0.0 inet6 addr: ::1/128 scope:host up loopback running mtu:65536 metric:1 rx packets:0 errors:0 dropped:0 overruns:0 frame:0 tx packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1 rx bytes:0 (0.0 b) tx bytes:0 (0.0 b)
可以看到這個(gè)容器的ip地址為172.17.0.2,現(xiàn)在我們到宿主機(jī)里看看ping 172.17.0.2能不能ping通。
答案當(dāng)然是能ping通,能ping通的原因就是我們的宿主機(jī)里知道目標(biāo)地址為172.17.0.1/16的路由信息,不信我們可以查看一下
alex@alex-lenovo-u310:~$ ip route default via 192.168.12.1 dev wlp3s0 proto static metric 600 169.254.0.0/16 dev docker0 scope link metric 1000 172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 192.168.12.0/24 dev wlp3s0 proto kernel scope link src 192.168.12.107 metric 600
從上面可以看出來(lái),172.17.0.0/16這個(gè)網(wǎng)段的數(shù)據(jù)包可以通過(guò)docker0這塊網(wǎng)卡發(fā)送出去。也就是說(shuō),目前宿主機(jī)有兩個(gè)ip,一個(gè)是192.168.12.107,用于連接實(shí)體的局域網(wǎng),一個(gè)是172.17.0.1,用來(lái)和docker容器通信,從這可以看出宿主機(jī)和路由器的作用是一致的。而docker容器只有一個(gè)ip就是172.17.0.2。如果docker容器想要訪(fǎng)問(wèn)外網(wǎng),那么它就會(huì)把數(shù)據(jù)包發(fā)送到網(wǎng)關(guān)172.17.0.1,然后由宿主機(jī)做nat發(fā)送到192.168.12.1/24這個(gè)網(wǎng)段的網(wǎng)關(guān)上。
不光宿主機(jī)可以ping通容器,而且由于在docker容器中默認(rèn)路由(網(wǎng)關(guān))是172.17.0.1,所以docker容器不光可以ping主機(jī)的172.17.0.1,還能ping通主機(jī)的另一個(gè)ip:192.168.12.107
此時(shí)我們的網(wǎng)絡(luò)拓?fù)淦鋵?shí)就變成了192.168.12.0/24這個(gè)網(wǎng)段里有個(gè)宿主機(jī),為了方便理解,我們把這個(gè)宿主機(jī)看成一個(gè)路由器,路由器下面是172.17.0.1/16這個(gè)網(wǎng)段。我們把docker容器看成實(shí)實(shí)在在的機(jī)器設(shè)備,連接在宿主機(jī)這個(gè)路由器的下面。這樣docker的拓?fù)浣Y(jié)構(gòu)就非常清晰了。我們可以發(fā)現(xiàn)這個(gè)拓?fù)浣Y(jié)構(gòu)其實(shí)非常的簡(jiǎn)單。就像家里上網(wǎng)的路由器一樣。打個(gè)比方:我家里有兩個(gè)路由器,一個(gè)路由器通過(guò)pppoe撥號(hào)連接公網(wǎng),內(nèi)網(wǎng)地址為192.168.12.1,另一個(gè)路由器連接在第一個(gè)路由器上面,wan口ip是192.168.12.107,lan口地址是172.17.0.1,我們的docker容器看成一個(gè)個(gè)的電腦接在第二個(gè)路由器lan上面,所以docker容器的ip為172.17.0.2。
第二個(gè)路由器(宿主機(jī))通過(guò)nat讓我們的電腦們(docker容器)可以訪(fǎng)問(wèn)互聯(lián)網(wǎng)。電腦們(docker容器們)可以互相ping通,也能ping通全部?jī)蓚€(gè)路由器。第二個(gè)路由器可以ping通電腦們,但是第一個(gè)路由器ping不同電腦們。如果還是不理解拓?fù)浣Y(jié)構(gòu),可以自己在家里買(mǎi)兩個(gè)路由器一前一后放上試試。
現(xiàn)在問(wèn)題來(lái)了,如果有一個(gè)電腦連接在第一個(gè)路由器的下面,和第二個(gè)路由器(宿主機(jī))平級(jí),其ip為192.168.12.113,現(xiàn)在它想ping通172.17.0.2這個(gè)docker容器,發(fā)現(xiàn)是ping不通的。同樣第一臺(tái)路由器自己也是ping不通docker容器的
原因很簡(jiǎn)單,這臺(tái)新計(jì)算機(jī)只能ping通同網(wǎng)段的設(shè)備,比如路由器2,因?yàn)樗麄兺瑢儆?92.168.12.1/24這個(gè)網(wǎng)段。而172.17.0.2/16這個(gè)網(wǎng)段它并不知道怎么路由過(guò)去,只能把目標(biāo)地址為172.17.0.1/16的數(shù)據(jù)包發(fā)給路由器一,可惜就連第一個(gè)路由器也不知道怎么個(gè)路由法。所以我們就ping不通了。
所以現(xiàn)在問(wèn)題就很好解決了,我們只需要告訴這臺(tái)新電腦或者第一個(gè)路由器到172.17.0.2/16這個(gè)網(wǎng)段的路徑就可以了。
于是我們可以在新電腦或者路由器一中這樣寫(xiě)
route add -net 172.17.0.1/16 gw 192.168.12.107
或者是
ip route add 172.17.0.1/16 via 192.168.12.107
普通路由器可以像這樣設(shè)置
現(xiàn)在新電腦訪(fǎng)問(wèn)172.17.0.2的數(shù)據(jù)包就會(huì)先被發(fā)送到宿主機(jī)(第二個(gè)路由器)上,然后宿主機(jī)再轉(zhuǎn)發(fā)到docker容器上,我們就把docker容器暴露到局域網(wǎng)里了。
但此時(shí)你會(huì)發(fā)現(xiàn)你在新計(jì)算機(jī)上還是ping不通,這是為什么呢。因?yàn)槁酚善鞫ㄋ拗鳈C(jī))對(duì)它的內(nèi)網(wǎng)機(jī)器也就是docker容器們?nèi)块_(kāi)啟了nat,源ip為172.17.0.2/16的數(shù)據(jù)包不會(huì)出現(xiàn)在宿主機(jī)以外的網(wǎng)絡(luò)中,因?yàn)樗麄儽籲at了。這個(gè)nat是docker進(jìn)程默認(rèn)自動(dòng)幫我們實(shí)現(xiàn)的,我們先看一下
alex@alex-lenovo-u310:~$ sudo iptables -t nat -l -n chain prerouting (policy accept) target prot opt source destination docker all -- 0.0.0.0/0 0.0.0.0/0 addrtype match dst-type local chain input (policy accept) target prot opt source destination chain output (policy accept) target prot opt source destination docker all -- 0.0.0.0/0 !127.0.0.0/8 addrtype match dst-type local chain postrouting (policy accept) target prot opt source destination masquerade all -- 172.17.0.0/16 0.0.0.0/0 masquerade tcp -- 172.17.0.2 172.17.0.2 tcp dpt:53 masquerade udp -- 172.17.0.2 172.17.0.2 udp dpt:53 chain docker (2 references) target prot opt source destination return all -- 0.0.0.0/0 0.0.0.0/0 dnat tcp -- 0.0.0.0/0 127.0.0.1 tcp dpt:5053 to:172.17.0.2:53 dnat udp -- 0.0.0.0/0 127.0.0.1 udp dpt:5053 to:172.17.0.2:53
注意那句masquerade all -- 172.17.0.0/16 0.0.0.0/0會(huì)導(dǎo)致所有172.17.0.0/16的數(shù)據(jù)包都不能到達(dá)docker以外的網(wǎng)絡(luò),所以我們要關(guān)掉這個(gè)nat,關(guān)掉很容易,我們只需刪掉這一條iptables規(guī)則就可以了。然后源ip為172.17.0.2的數(shù)據(jù)包就可以出現(xiàn)在192.168.12.1/24的網(wǎng)絡(luò)中了。
sudo iptables -t nat -d postrouting 3
但是把nat關(guān)掉了以后,雖然內(nèi)網(wǎng)可以互ping了,但是docker容器可能上不去網(wǎng)呀。第一個(gè)路由器如果自動(dòng)nat 了172.17.0.2還好,但要是沒(méi)有人給docker容器做nat,docker容器就不能上網(wǎng)了,那我們的cdns也就沒(méi)法用了。那么如何既保證docker容器訪(fǎng)問(wèn)外網(wǎng)的數(shù)據(jù)包被nat,又保證內(nèi)網(wǎng)通信不被nat呢?只要稍微修改一下iptables規(guī)則就好了,如下
sudo iptables -t nat -a postrouting -s 172.17.0.2 ! -d 192.168.12.1/24 -j masquerade
上面的iptables規(guī)則通過(guò)對(duì)內(nèi)外網(wǎng)流量的分離實(shí)現(xiàn)區(qū)別的nat對(duì)待,就可以既保證docker容器正常上網(wǎng),也可以被內(nèi)網(wǎng)其他主機(jī)訪(fǎng)問(wèn)了。
可能會(huì)有這么一種情況,上面所說(shuō)的第一臺(tái)路由器不是什么智能路由器,或者你沒(méi)有權(quán)限在那個(gè)路由器上配置路由條目,讓目標(biāo)為172.17.0.0/16的數(shù)據(jù)包通過(guò)路由器進(jìn)行路由。同時(shí)你的局域網(wǎng)其他電腦是xp系統(tǒng)的,也沒(méi)法手動(dòng)配置路由規(guī)則,這該怎么辦呢?
現(xiàn)在以要訪(fǎng)問(wèn)docker容器的局域網(wǎng)主機(jī)為windows xp系統(tǒng)為例,雖然winxp不能手動(dòng)配置路由規(guī)則,但是我們可以配置網(wǎng)關(guān),只要我們把網(wǎng)關(guān)設(shè)置為192.168.0.107也就是我們的宿主機(jī),目標(biāo)地址為172.17.0.0/16的ip包就會(huì)發(fā)送到宿主機(jī)上,而宿主機(jī)不同于第一個(gè)路由器,它是知道如何路由這些ip包的。于是我們就可以在winxp上ping通docker容器了
以上就是關(guān)于“Docker容器怎么通過(guò)獨(dú)立IP暴露給局域網(wǎng)”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。