Docker Network 網路
在 Docker 的世界中,容器不僅是獨立的,它們通常需要相互通訊(例如:Web Server 連接資料庫)或者與外界連網。Docker 提供了一套強大的網路子系統,讓開發者能以虛擬的方式管理這些通訊路徑。
本章將帶你掌握 Docker 網路的核心驅動程式與實戰技巧。
核心網路驅動程式
Docker 使用驅動程式來處理網路通訊。了解不同驅動程式的適用場景是優化架構的第一步:
- Bridge (橋接模式):
- 用途:預設模式,適用於單一主機上的容器通訊。
- 特性:容器透過虛擬網橋
docker0取得內網 IP。
- Host (主機模式):
- 用途:追求極致效能的應用(如高效能 Web Server)。
- 特性:容器直接使用主機的網路棧,PORT 不需要對應,效率最高,但缺乏隔離。
- Overlay (覆蓋網路):
- 用途:多主機通訊、Docker Swarm 或集群架構。
- 特性:在多台實體機之間建立一個虛擬隧道,讓不同主機上的容器像在同一個區域網路。
- Macvlan:
- 用途:需要讓容器擁有實體網路身分(MAC 位址)的情境。
- 特性:容器會直接連接到實體網路,適合處理舊有系統與實體機之間的通訊。
- None:
- 用途:高安全性、不需要聯網的運算工作。
- 特性:完全停用網路棧。
為何要自定義網路:服務發現 (Service Discovery)
Docker 內建了一套 DNS 服務。當容器加入自定義網路後,它們可以透過「容器名稱」或「網路別名」來互相通訊,這稱為服務發現。
服務發現的關鍵機制
- 自動解析:Docker 會自動維護一套內部 DNS,將
db這個名稱轉化為目前的 IP。容器即便重啟導致 IP 改變,名稱通訊依然有效。 - 預設 Bridge vs. 自定義網路:
- 在「預設
bridge」中:不支援 DNS 解析,必須手動查 IP 或使用--link(已過時)。 - 在「自定義網路」中:原生支援 DNS 解析,這是現代 Docker 部署的標準做法。
- 在「預設
推薦做法:為每個專案建立獨立的 Bridge 網路。
現在,你的 Web 容器可以直接透過 http://db 訪問資料庫。
進階實戰:多重網路與安全隔離
在生產環境中,我們常讓一個容器(如 Nginx 反向代理)連接多個網路,以求達到「外網接入」與「內網資料隔離」。
# 1. 建立前端網路 (對應外部來源) 與 後端網路 (內部資料庫)
docker network create frontend-net
docker network create backend-net
# 2. 資料庫只加入 backend-net (隔離,外部無法存取)
docker run -d --name mysql --network backend-net -e MYSQL_ROOT_PASSWORD=pw mysql:8.0
# 3. Nginx 同時接上兩個網路
docker run -d --name proxy --network frontend-net -p 80:80 nginx
docker network connect backend-net proxy
這樣一來,proxy 容器既能接收外部請求,也能連到 mysql;但 mysql 由於不在 frontend-net 裡,壞人就算突破了 proxy 也很難直接摸到它。
外部訪問:埠號映射 (Port Mapping)
當我們想從本機瀏覽器連到容器時,必須使用 -p 參數:
docker run -p [主機埠號]:[容器埠號] nginx
-p 80:80:將主機的 80 對應到容器 80。-p 127.0.0.1:8080:80:只允許本地存取該容器。-P(大寫):自動隨機分配主機的高位埠號到容器定義的 Exposed 埠。
Host 模式:追求極致效能的網路選擇
在某些對性能極度要求的場景中,你可能不希望網路封包經過 Docker 的虛擬層轉換,這時 host 模式就是最佳選擇。
Host 模式的運作原理
當容器使用 Host 模式啟動時,它不會獲得獨立的 IP 位址。相反地,它會直接共用宿主機的網路卡、IP 以及埠號資源。這意味著:
- 無效能損耗:省去了 Docker 網橋與 NAT (網路地址轉換) 的處理負擔。
- 埠號衝突:如果容器監聽 80 埠,宿主機的 80 埠就會被占走。你不能同時啟動兩個在 Host 模式下都監聽 80 埠的容器。
指令用法:--network host
使用 --network host 參數即可啟動:
# 啟動一個 Nginx 容器並使用主機網路
docker run -d --name my-host-nginx --network host nginx
-p 參數會被完全忽略。因為容器就是宿主機,不需要做埠號對應。什麼時候該用 Host 模式?
- 追求極致效能:例如負載平衡器、資料庫的核心組件。
- 網路診斷工具:當你需要容器內的程式能直接讀取宿主機網路流量。
- 簡化通訊:當你不需要網路隔離,且希望容器服務能直接被內網存取。
安全警告:Host 模式的風險
這是一個強大但也危險的模式:
- 缺乏隔離:容器內的惡意程式碼可能更容易存取宿主機內私有的網路服務(如僅監聽 127.0.0.1 的本地資料庫)。
- 缺乏命名空間保護:容器可以對宿主機的網路配置(如修改 Hostname)產生影響。
管理網路的常用指令
查看網路列表
docker network ls
查看特定網路詳細資訊 (查看有哪些容器在裡面)
docker network inspect my-app-net
將運作中的容器連接到新網路
docker network connect my-app-net old-container
斷開連線
docker network disconnect my-app-net old-container
進階:Docker v29 與 nftables
在 Docker v29 中,引入了對 nftables 的實驗性支援。
傳統上 Docker 使用 iptables 來管理 Linux 的核心防火牆規則,但許多現代 Linux 發行版(如 Debian 11+, RHEL 9+)已經轉向效能更好的 nftables。這項更新讓 Docker 在現代 Linux 主機上的網路管理更穩定且更具前瞻性。
如果你想測試這項功能,可以在 daemon.json 中配置:
{
"ip6tables": true,
"experimental": true
}
檢視容器在網路中的真正狀態
如果你想看某個容器目前被分配到什麼 IP,除了 inspect 網路以外,也可以針對容器使用:
# 快速過濾出容器的 IP 位址
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [容器名稱]
清理沒在用的網路
隨著開發時間變久,會殘留許多沒在用的自定義網路,使用以下指令一鍵清理:
docker network prune
總結與最佳實踐
- 優先使用自定義 Bridge:除了確保 DNS 自動解析,還能提供專屬該應用的網路隔離。
- 依賴名稱而非 IP:永遠透過容器名稱(或
--network-alias)來通訊。 - 最小化埠號暴露:只有需要對外公開的服務(如 Web 前端)才使用
-p,內部的資料庫通訊應隱藏在網路內。 - 考慮網路效能:高性能場景首選
host,跨主機場景首選overlay,一般應用首選bridge。