docker proxy實(shí)現(xiàn)原理解析
docker-proxy 是 Docker 網(wǎng)絡(luò)架構(gòu)中的一個(gè)“傳聲筒”。當(dāng)你啟動(dòng)一個(gè)容器并使用 -p 參數(shù)映射端口時(shí),它就在幕后默默工作。如下的一個(gè)docker-compose配置:

注意這里的端口映射,就類似于你運(yùn)行 docker run -p 30003:30003 的命令時(shí),你實(shí)際上是要求宿主機(jī)將發(fā)往 30003 端口的流量轉(zhuǎn)發(fā)到容器內(nèi)部的 30003 端口。
為了實(shí)現(xiàn)這個(gè)轉(zhuǎn)發(fā),Docker 使用了兩種機(jī)制:
- DNAT (iptables 規(guī)則): 這是主要方式,效率極高,直接在內(nèi)核層面處理流量。
- docker-proxy: 這是一個(gè)運(yùn)行在用戶態(tài)(Userland)的小程序。每當(dāng)你映射一個(gè)端口,Docker 就會(huì)為該端口啟動(dòng)一個(gè)獨(dú)立的
docker-proxy進(jìn)程。
以上兩個(gè)動(dòng)作是由docker自動(dòng)完成的,這時(shí),你使用如下命令(netstat, ps)可以查看到該docker-proxy進(jìn)程:

但是,如果你使用命令sudo kill -9 2152 把這個(gè)docker-proxy進(jìn)程殺死,你再次訪問(wèn)該主機(jī)的30003端口,仍然可以正常訪問(wèn)?。。〉悄?code>ss 或 netstat搜索不到任何關(guān)于30003端口的信息。
1. 為什么進(jìn)程殺了,網(wǎng)頁(yè)還能訪問(wèn)?
這就是 Docker 的“雙保險(xiǎn)”機(jī)制:
- 保險(xiǎn) A (iptables): 只要容器還在運(yùn)行,Docker 就會(huì)在 Linux 內(nèi)核中寫入一條
iptables轉(zhuǎn)發(fā)規(guī)則(DNAT)。這條規(guī)則在內(nèi)核態(tài)生效,不依賴任何進(jìn)程。 - 保險(xiǎn) B (docker-proxy): 這是一個(gè)用戶態(tài)進(jìn)程,主要負(fù)責(zé)處理一些
iptables覆蓋不到的邊角情況。
當(dāng)你殺掉 docker-proxy 進(jìn)程后,內(nèi)核態(tài)的 iptables 規(guī)則依然穩(wěn)如泰山。所以,外部流量打到 30003 時(shí),內(nèi)核直接把包轉(zhuǎn)給了容器,網(wǎng)頁(yè)自然能打開(kāi)。這時(shí)你輸入命令,大概率會(huì)看到:
[root@localhost ~]# sudo iptables -t nat -L DOCKER -n | grep 30003 DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:30003 to:172.21.0.3:30003
2. 為什么ss搜不到了?
ss 和 netstat 查的是系統(tǒng)中的 Socket 監(jiān)聽(tīng)表。
- 當(dāng)
docker-proxy運(yùn)行時(shí),它會(huì)占用(Bind)30003端口,ss就能看到它。 - 你把它殺了,這個(gè)端口在用戶態(tài)就處于“空閑”狀態(tài)。
- 但是,內(nèi)核
iptables就像一個(gè)“隱形攔截者”,它在數(shù)據(jù)包還沒(méi)到達(dá) Socket 層之前就把包搶走了。
3. 會(huì)有什么后果?
雖然現(xiàn)在訪問(wèn)正常,但殺掉 docker-proxy 可能會(huì)導(dǎo)致以下小問(wèn)題:
- 宿主機(jī)局部回環(huán)失效: 在某些配置下,你在宿主機(jī)本地執(zhí)行
curl localhost:30003可能會(huì)失?。ūM管從外網(wǎng)訪問(wèn)是好的)。 - 狀態(tài)不一致: Docker 此時(shí)并不知道你手動(dòng)殺了它的組件。當(dāng)你下次
docker stop或rm這個(gè)容器時(shí),Docker 可能會(huì)因?yàn)檎也坏皆撨M(jìn)程而報(bào)一個(gè)小錯(cuò)誤(盡管它通常會(huì)自動(dòng)忽略)。
4. 怎么恢復(fù)?
如果你想讓 docker-proxy 重新出現(xiàn),最簡(jiǎn)單的方法是重啟容器:
docker restart web-ui
重啟后,Docker 會(huì)重新創(chuàng)建 iptables 規(guī)則并啟動(dòng)一個(gè)新的 docker-proxy 進(jìn)程。
總結(jié):
一個(gè)很重要的結(jié)論:Docker 的端口映射本質(zhì)上是內(nèi)核行為(iptables),docker-proxy 只是一個(gè)輔助。 只要內(nèi)核規(guī)則在,服務(wù)就不會(huì)斷。
到此這篇關(guān)于docker proxy實(shí)現(xiàn)原理解析的文章就介紹到這了,更多相關(guān)docker proxy原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
docker imageid 和 digest區(qū)別解析
在Docker中,image ID和digest是兩個(gè)不同的標(biāo)識(shí)符,用于唯一標(biāo)識(shí)和引用Docker鏡像的不同方面,這篇文章主要介紹了docker imageid 和 digest區(qū)別,需要的朋友可以參考下2023-06-06
Docker如何給Springboot項(xiàng)目動(dòng)態(tài)傳參的實(shí)現(xiàn)方法
這篇文章主要介紹了Docker如何給Springboot項(xiàng)目動(dòng)態(tài)傳參的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
keepalived+nginx+httpd實(shí)現(xiàn)的雙機(jī)熱備+負(fù)載均衡
本文主要介紹了keepalived + nginx + httpd 實(shí)現(xiàn)的雙機(jī)熱備+負(fù)載均衡,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-07-07
Docker服務(wù)器存儲(chǔ)資源池不足的問(wèn)題解決
這篇文章主要給大家介紹了關(guān)于Docker服務(wù)器存儲(chǔ)資源池不足的問(wèn)題解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
k8s和Docker關(guān)系簡(jiǎn)單說(shuō)明
這篇文章主要介紹了k8s和Docker關(guān)系簡(jiǎn)單說(shuō)明,本文利于圖文講解的很透徹,有需要的同學(xué)可以研究下2021-03-03

