如何解決docker容器訪問不了外部網(wǎng)絡(luò)問題
前戲
事情的起因是我在服務(wù)器A中部署了一個用docker實現(xiàn)的java項目,這個項目中依賴于另一臺服務(wù)器中的elasticsearch,但是一直顯示無法連接,

進入容器ping一下試試看

很顯然,網(wǎng)絡(luò)不通
docker中的bridge網(wǎng)絡(luò)詳解
在 Docker 中,bridge 網(wǎng)絡(luò) 是最常用的網(wǎng)絡(luò)模式之一,它通過虛擬網(wǎng)橋(如默認的 docker0)來連接容器。
容器之間以及容器與外部網(wǎng)絡(luò)的通信,需要依賴 Linux 主機的 IP 轉(zhuǎn)發(fā)功能。
這是因為 Docker 網(wǎng)絡(luò)模型本質(zhì)上是通過 Linux 的虛擬網(wǎng)絡(luò)設(shè)備、iptables 和 IP 轉(zhuǎn)發(fā)等內(nèi)核功能來實現(xiàn)的。
1. 什么是 Docker bridge 網(wǎng)絡(luò)?
當(dāng) Docker 啟動時,它會自動創(chuàng)建一個名為 docker0 的虛擬網(wǎng)橋,類似于一個軟件交換機。所有使用 bridge 模式運行的容器,都會自動連接到 docker0 上,并被分配一個 IP 地址。
2. IP 轉(zhuǎn)發(fā)的作用
當(dāng)你在 Docker 中使用 bridge 網(wǎng)絡(luò)時,IP 轉(zhuǎn)發(fā) 起到以下關(guān)鍵作用:
- 容器與外部網(wǎng)絡(luò)的通信:當(dāng)容器 A(在 docker0 網(wǎng)絡(luò)中)想要訪問外部網(wǎng)絡(luò)(比如互聯(lián)網(wǎng)或其他主機)時,數(shù)據(jù)包會通過 docker0 虛擬網(wǎng)橋被發(fā)送到主機的網(wǎng)絡(luò)接口(如 eth0)。在這種情況下,主機必須啟用 IP 轉(zhuǎn)發(fā)功能,才能將這些數(shù)據(jù)包從 docker0 轉(zhuǎn)發(fā)到外部網(wǎng)絡(luò)。
- 容器之間的通信:容器 A 和容器 B 在 docker0 虛擬網(wǎng)橋上被分配了不同的 IP 地址,Linux 需要啟用 IP 轉(zhuǎn)發(fā)來在它們之間路由數(shù)據(jù)包。例如,容器 A 的 IP 地址為 172.17.0.2,容器 B 的 IP 地址為 172.17.0.3,如果 A 需要與 B 通信,數(shù)據(jù)包需要通過 docker0 網(wǎng)橋進行轉(zhuǎn)發(fā)。
- NAT(網(wǎng)絡(luò)地址轉(zhuǎn)換)和外部訪問:為了使容器能夠訪問外部網(wǎng)絡(luò)(如互聯(lián)網(wǎng)),Docker 通常會通過 NAT 來隱藏容器的內(nèi)部 IP 地址(例如 172.17.0.x),這需要主機具有 IP 轉(zhuǎn)發(fā)能力。Docker 會通過 iptables 將內(nèi)部容器網(wǎng)絡(luò)的流量進行 SNAT(源地址轉(zhuǎn)換),并轉(zhuǎn)發(fā)到主機的物理網(wǎng)絡(luò)接口上。
3. IP 轉(zhuǎn)發(fā)如何幫助 Docker 網(wǎng)絡(luò)工作?
在 Linux 主機中,IP 轉(zhuǎn)發(fā)的配置位于 /proc/sys/net/ipv4/ip_forward。如果該值為 0,則表示 IP 轉(zhuǎn)發(fā)被禁用;如果該值為 1,則表示啟用。Docker 依賴這個設(shè)置來實現(xiàn)容器與外部網(wǎng)絡(luò)之間的通信。
當(dāng) Docker 創(chuàng)建 bridge 網(wǎng)絡(luò)時,內(nèi)部機制包括以下幾步:
- 創(chuàng)建虛擬網(wǎng)橋(如 docker0**)**。
- 給每個連接到該網(wǎng)橋的容器分配一個虛擬網(wǎng)卡(veth 設(shè)備)。
- 配置 IP 轉(zhuǎn)發(fā):確保 Linux 主機啟用了 IP 轉(zhuǎn)發(fā),以便將不同網(wǎng)絡(luò)接口之間的數(shù)據(jù)包進行轉(zhuǎn)發(fā)。
Docker 通過這種方式,將每個容器的 veth 設(shè)備與虛擬網(wǎng)橋 docker0 連接,形成一個橋接網(wǎng)絡(luò)。Linux 內(nèi)核的 IP 轉(zhuǎn)發(fā)機制則負責(zé)管理這些網(wǎng)絡(luò)接口之間的通信。
4. 配置 IP 轉(zhuǎn)發(fā)的步驟
在 Docker 主機上啟用 IP 轉(zhuǎn)發(fā)通常是自動的,但如果你需要手動啟用或進行故障排查,可以參考以下步驟:
- 檢查 IP 轉(zhuǎn)發(fā)是否啟用:
cat /proc/sys/net/ipv4/ip_forward - 臨時啟用 IP 轉(zhuǎn)發(fā)(在系統(tǒng)重啟前有效):
echo 1 > /proc/sys/net/ipv4/ip_forward - 永久啟用 IP 轉(zhuǎn)發(fā):編輯 /etc/sysctl.conf 文件,添加或修改以下內(nèi)容:
net.ipv4.ip_forward = 1
然后運行以下命令以應(yīng)用:sysctl -p
5. bridge 網(wǎng)絡(luò)中的 NAT 和 iptables
為了使容器能夠訪問外部網(wǎng)絡(luò),Docker 會自動配置 NAT 規(guī)則。Docker 默認會在 docker0 網(wǎng)橋上創(chuàng)建 iptables 規(guī)則,使得從內(nèi)部網(wǎng)絡(luò)發(fā)往外部的流量進行 SNAT(源地址轉(zhuǎn)換)。
這就意味著,來自容器的請求會以主機的 IP 地址作為源 IP 發(fā)往外部網(wǎng)絡(luò),這樣容器之間和容器與外部網(wǎng)絡(luò)之間的通信才得以實現(xiàn)。
例如:
?Docker 會創(chuàng)建如下的 iptables 規(guī)則來進行 NAT:
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
解決
可以認真看一下上面的,里面就有解決方案,我這里僅臨時展示解決一下
執(zhí)行
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

加餐
明明服務(wù)器A可以telnet服務(wù)器B的es服務(wù),但是還會報錯

在服務(wù)器B進行抓包可以看到如下

顯示被拒絕了,這個情況我是感到很無語的
進入服務(wù)器A中的java容器去ping一下服務(wù)器B的地址,你會發(fā)現(xiàn)它好了
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
微信小程序Docker+Nginx環(huán)境配置業(yè)務(wù)域名驗證文件的操作方法
本文介紹了如何在DockerCompose+Nginx環(huán)境下配置并訪問靜態(tài)驗證文件,首先下載驗證文件并將其掛載到容器中,然后修改Nginx配置文件使其能夠正確返回請求路徑下的靜態(tài)文件,最后,測試訪問驗證文件并提交業(yè)務(wù)域名,感興趣的朋友跟隨小編一起看看吧2025-01-01
淺談Docker Desktop for Linux和Docker Engine
本文主要介紹了Docker Desktop for Linux和Docker Engine區(qū)別,具有一定的參考價值,感興趣的可以了解一下2023-10-10

