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

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

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

