目錄
Docker Network 基礎
什麼是 Docker Network?
Docker Network 是 Docker 提供的網路抽象層,讓容器之間、容器與外部網路之間能夠通訊。
為什麼需要 Network?
# 問題 1:Container 之間如何通訊?
docker run -d --name web nginx
docker run -d --name db mysql
# web 如何連接到 db?
# 問題 2:如何從外部訪問 Container?
docker run -d nginx
# 如何從瀏覽器訪問 nginx?
# Network 解決方案
docker network create mynet
docker run -d --network mynet --name db mysql
docker run -d --network mynet --name web nginx
# web 可以直接用 'db' 這個名稱連接!
核心概念
宿主機 (Host)
├── eth0 (實體網卡)
├── docker0 (虛擬網橋)
│ ├── veth1 ← 連接到 容器A
│ └── veth2 ← 連接到 容器B
└── 容器 A, B, C...
關鍵元件:
- docker0:預設的虛擬網橋(類似虛擬交換機)
- veth pair:虛擬網路介面對(一端在容器內,一端在宿主機)
- Network Namespace:每個容器有獨立的網路空間
預設網路
Docker 安裝後會自動建立三個網路:
docker network ls
輸出:
NETWORK ID NAME DRIVER SCOPE
abc123def456 bridge bridge local
def456ghi789 host host local
ghi789jkl012 none null local
網路模式對比
| 特性 | Bridge | Host | None | Container | Custom |
|---|---|---|---|---|---|
| 隔離性 | 中等 | 低 | 高 | 低 | 中等 |
| 效能 | 好 | 最佳 | N/A | 好 | 好 |
| DNS 解析 | 基本 | N/A | N/A | 共享 | 完整 |
| Port 衝突 | 無 | 可能 | N/A | 共享 | 無 |
| 使用複雜度 | 簡單 | 簡單 | 簡單 | 中等 | 中等 |
| 適用場景 | 一般應用 | 高效能 | 安全隔離 | 特殊需求 | 生產環境 |
網路架構圖
Bridge 網路架構(預設)
Host 網路架構
┌──────────────────────────────────────┐
│ 主機網路 │
│ │
│ ┌──────────┐ │
│ │Container │ ← 直接使用主機網路 │
│ │ web │ │
│ └──────────┘ │
│ ↕ │
│ eth0 (主機網卡) │
└──────────────────────────────────────┘
Custom Network 多層架構
網路驅動類型
1. Bridge(橋接網路)- 預設
用途:單一宿主機上的容器通訊
原理:
宿主機
├── docker0 (172.17.0.1)
│ ├── container1 (172.17.0.2)
│ ├── container2 (172.17.0.3)
│ └── container3 (172.17.0.4)
└── eth0 → 外部網路
建立與使用:
# 使用預設 bridge(不推薦)
docker run -d nginx
# 建立自訂 bridge(推薦)
docker network create my-bridge
# 使用自訂 bridge
docker run -d --name web --network my-bridge nginx
特性:
- ✅ 容器之間可以互相通訊
- ✅ 可以對外部網路進行 NAT
- ✅ 自訂 bridge 支援容器名稱解析(DNS)
- ❌ 預設 bridge 不支援容器名稱解析(只能用 IP)
範例:
# 建立自訂網路
docker network create --driver bridge my-net
# 啟動容器並加入網路
docker run -d --name db --network my-net postgres
docker run -d --name app --network my-net myapp
# app 容器可以用 "db" 這個名稱連接資料庫
# 連接字串:postgresql://db:5432/mydb
2. Host(主機網路)
用途:容器直接使用宿主機的網路
原理:
宿主機 (192.168.1.100)
├── eth0
└── container (共用宿主機的網路介面)
使用:
docker run -d --network host nginx
特性:
- ✅ 效能最好(無網路轉換)
- ✅ 容器直接綁定宿主機的 port
- ❌ 沒有網路隔離
- ❌ 不能在同一台機器上執行多個相同 port 的容器
- ⚠️ 僅在 Linux 上完全支援
使用情境:
- 需要極高網路效能
- 需要直接存取宿主機網路介面
- 監控或網路工具容器
範例:
# Nginx 直接綁定宿主機的 80 port
docker run -d --network host nginx
# 可以直接存取:http://<宿主機IP>:80
3. None(無網路)
用途:完全隔離網路
使用:
docker run -d --network none alpine sleep 3600
特性:
- 容器只有 loopback 介面(127.0.0.1)
- 無法連接外部網路
- 完全的網路隔離
使用情境:
- 安全性要求極高的應用
- 批次處理作業(不需要網路)
- 測試環境
4. Container(容器網路)
用途:共用其他容器的網路
原理:
容器A (主容器)
├── eth0 (172.17.0.2)
└── 容器B (共用容器A的網路)
使用:
# 啟動主容器
docker run -d --name container1 nginx
# 共用 container1 的網路
docker run -d --network container:container1 alpine sleep 3600
特性:
- 兩個容器共用相同的 IP 位址
- 可以透過 localhost 通訊
- 常用於 sidecar 模式(如 Kubernetes Pod)
使用情境:
- Sidecar 容器(日誌收集、監控)
- 服務網格(Service Mesh)
- 需要緊密網路耦合的容器
5. Overlay(覆蓋網路)
用途:跨多台宿主機的容器通訊(Docker Swarm)
原理:
宿主機1 宿主機2
├── container1 ←→ ├── container3
└── container2 └── container4
↓ ↓
Overlay Network (虛擬網路層)
建立:
# 需要在 Swarm 模式下
docker swarm init
# 建立 overlay 網路
docker network create --driver overlay my-overlay
# 建立服務並使用 overlay
docker service create --name web --network my-overlay nginx
特性:
- ✅ 支援跨主機通訊
- ✅ 內建加密選項
- ✅ 自動服務發現
- ❌ 需要 Swarm 模式或 Kubernetes
使用情境:
- 微服務架構(跨多台機器)
- Docker Swarm 叢集
- 分散式應用
6. Macvlan(MAC VLAN)
用途:讓容器擁有獨立的 MAC 位址(像實體機器)
原理:
宿主機網路 (192.168.1.0/24)
├── 宿主機 (192.168.1.100)
├── 容器1 (192.168.1.101) ← 獨立 MAC
└── 容器2 (192.168.1.102) ← 獨立 MAC
建立:
# 建立 macvlan 網路
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 my-macvlan
# 使用 macvlan
docker run -d --network my-macvlan --ip=192.168.1.101 nginx
特性:
- ✅ 容器在區域網路中像實體機器
- ✅ 可以直接被外部裝置存取
- ⚠️ 網卡需要支援混雜模式
- ⚠️ 無法與宿主機直接通訊
使用情境:
- 需要容器直接在區域網路中可見
- DHCP 伺服器容器
- 網路監控工具
容器網路通訊
容器名稱解析(DNS)
自訂 bridge 網路:
# 建立網路
docker network create my-net
# 啟動容器
docker run -d --name db --network my-net postgres
docker run -d --name web --network my-net nginx
# 在 web 容器內可以用名稱連接
docker exec web ping db # ✅ 可以 ping 通
預設 bridge 網路:
# 使用預設網路
docker run -d --name db postgres
docker run -d --name web nginx
# 無法用名稱連接
docker exec web ping db # ❌ 無法解析
Port 映射(Port Mapping)
語法:
-p <宿主機port>:<容器port>
-p <宿主機IP>:<宿主機port>:<容器port>
範例:
# 映射單一 port
docker run -d -p 8080:80 nginx
# 存取:http://localhost:8080
# 映射到特定 IP
docker run -d -p 127.0.0.1:8080:80 nginx
# 只能從本機存取
# 映射多個 port
docker run -d -p 8080:80 -p 8443:443 nginx
# 映射所有 port
docker run -d -P nginx
# Docker 自動分配隨機 port
查看 port 映射:
docker port <container>
容器間通訊模式
模式 1:透過容器名稱(推薦)
# 前提:在同一個自訂網路
docker network create app-net
docker run -d --name redis --network app-net redis
docker run -d --name api --network app-net myapi
# 在 api 容器中可以用 "redis" 連接
# 連接字串:redis://redis:6379
模式 2:透過 IP 位址
# 查看容器 IP
docker inspect redis | grep IPAddress
# 輸出:172.18.0.2
# 在其他容器中用 IP 連接
# 連接字串:redis://172.18.0.2:6379
⚠️ 注意:IP 可能會改變,不建議使用
模式 3:透過網路別名(Alias)
# 建立網路
docker network create mynet
# 啟動容器並設定多個別名
docker run -d \
--network mynet \
--network-alias database \
--network-alias db \
--name mysql \
mysql
# 可以用多個名稱訪問
docker exec app ping mysql # ✅
docker exec app ping database # ✅
docker exec app ping db # ✅
模式 4:透過 link(已棄用)
# 舊方法,不推薦
docker run -d --name redis redis
docker run -d --link redis:redis myapi
網路指令詳解
1. docker network ls - 列出網路
# 列出所有網路
docker network ls
# 過濾特定驅動
docker network ls --filter driver=bridge
2. docker network create - 建立網路
基本語法:
docker network create [OPTIONS] NETWORK_NAME
常用選項:
# 建立基本 bridge 網路
docker network create my-net
# 指定子網路和閘道
docker network create \
--subnet=172.20.0.0/16 \
--gateway=172.20.0.1 \
my-net
# 指定 IP 範圍
docker network create \
--subnet=172.20.0.0/16 \
--ip-range=172.20.10.0/24 \
my-net
# 建立 overlay 網路(需要 Swarm)
docker network create --driver overlay my-overlay
# 建立 macvlan 網路
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 my-macvlan
3. docker network connect - 連接容器到網路
# 連接執行中的容器到網路
docker network connect my-net container1
# 指定 IP
docker network connect --ip 172.20.0.10 my-net container1
# 指定別名(DNS alias)
docker network connect --alias db my-net postgres
一個容器可以連接到多個網路:
docker network connect net1 container1
docker network connect net2 container1
4. docker network disconnect - 斷開容器與網路
# 斷開連接
docker network disconnect my-net container1
# 強制斷開
docker network disconnect -f my-net container1
5. docker network inspect - 查看網路詳細資訊
# 查看網路資訊
docker network inspect my-net
# 查看特定欄位
docker network inspect my-net --format='{{.IPAM.Config}}'
# 查看連接到此網路的容器
docker network inspect my-net --format='{{range .Containers}}{{.Name}} {{end}}'
輸出範例:
[
{
"Name": "my-net",
"Driver": "bridge",
"IPAM": {
"Config": [
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
]
},
"Containers": {
"abc123": {
"Name": "web",
"IPv4Address": "172.20.0.2/16"
}
}
}
]
6. docker network rm - 刪除網路
# 刪除網路
docker network rm my-net
# 刪除多個網路
docker network rm net1 net2 net3
# 刪除所有未使用的網路
docker network prune
7. docker network prune - 清理未使用的網路
# 刪除所有未使用的網路
docker network prune
# 不詢問直接刪除
docker network prune -f
# 刪除特定時間之前建立的網路
docker network prune --filter "until=24h"
實際應用場景
場景 1:Web 應用 + 資料庫
# 建立專用網路
docker network create webapp-net
# 啟動資料庫(不對外暴露)
docker run -d \
--name db \
--network webapp-net \
-e POSTGRES_PASSWORD=secret \
postgres
# 啟動後端 API(對外暴露 8080)
docker run -d \
--name api \
--network webapp-net \
-p 8080:8080 \
-e DATABASE_URL=postgresql://db:5432/mydb \
myapi
# 啟動前端(對外暴露 80)
docker run -d \
--name web \
--network webapp-net \
-p 80:80 \
myfrontend
網路架構:
外部網路
↓
宿主機 :80, :8080
↓
webapp-net (內部)
├── web (前端)
├── api (後端)
└── db (資料庫,不對外)
場景 2:微服務架構
# 建立前端網路(對外)
docker network create frontend
# 建立後端網路(內部)
docker network create backend
# API Gateway(連接兩個網路)
docker run -d \
--name gateway \
--network frontend \
-p 80:80 \
nginx
docker network connect backend gateway
# 微服務(只在後端網路)
docker run -d --name user-service --network backend user-svc
docker run -d --name order-service --network backend order-svc
docker run -d --name payment-service --network backend payment-svc
# 資料庫(只在後端網路)
docker run -d --name db --network backend postgres
網路架構:
frontend (對外)
├── gateway (API Gateway)
│ └── 同時連接到 backend
│
backend (內部)
├── gateway
├── user-service
├── order-service
├── payment-service
└── db
場景 3:開發環境隔離
# 專案A的網路
docker network create projectA-net
docker run -d --name projectA-db --network projectA-net postgres
docker run -d --name projectA-redis --network projectA-net redis
# 專案B的網路
docker network create projectB-net
docker run -d --name projectB-db --network projectB-net postgres
docker run -d --name projectB-redis --network projectB-net redis
# 兩個專案完全隔離,不會互相影響
場景 4:使用 Docker Compose
# docker-compose.yml
version: '3.8'
services:
web:
image: nginx
ports:
- "80:80"
networks:
- frontend
- backend
api:
image: myapi
networks:
- backend
depends_on:
- db
db:
image: postgres
networks:
- backend
environment:
POSTGRES_PASSWORD: secret
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 不能存取外部網路
啟動:
docker-compose up -d
最佳實踐
1. 使用自訂網路
✅ 推薦:
docker network create my-app
docker run -d --name db --network my-app postgres
docker run -d --name api --network my-app myapi
❌ 避免:
# 使用預設 bridge(無容器名稱解析)
docker run -d --name db postgres
docker run -d --name api --link db myapi
2. 網路隔離
原則:
- 前端網路:對外暴露的服務
- 後端網路:內部服務(資料庫、快取)
- 資料庫只在後端網路,不對外暴露
docker network create frontend
docker network create backend
# API Gateway 同時連接兩個網路
docker run -d --name gateway --network frontend nginx
docker network connect backend gateway
# 資料庫只在後端
docker run -d --name db --network backend postgres
3. 不要暴露不必要的 port
✅ 推薦:
# 資料庫不對外暴露
docker run -d --name db --network backend postgres
# 只有需要外部存取的服務才映射 port
docker run -d --name web --network frontend -p 80:80 nginx
❌ 避免:
# 不必要地暴露資料庫 port
docker run -d -p 5432:5432 postgres
4. 使用環境變數配置
docker run -d \
--name api \
--network backend \
-e DATABASE_HOST=db \
-e DATABASE_PORT=5432 \
-e REDIS_HOST=redis \
myapi
5. 網路命名規範
命名格式:{project}-{layer}-net
# 使用專案名稱 + 層級
docker network create myapp-frontend-net
docker network create myapp-backend-net
docker network create myapp-database-net
docker network create myapp-cache-net
# 或使用環境作為前綴
docker network create dev-network
docker network create prod-network
疑難排解
1. 檢查容器網路配置
# 查看容器的網路資訊
docker inspect <container> | grep -A 20 NetworkSettings
# 查看容器 IP
docker inspect <container> --format='{{.NetworkSettings.IPAddress}}'
# 查看容器連接的網路
docker inspect <container> --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
2. 測試容器間連接
# 進入容器測試
docker exec -it container1 sh
# 測試 DNS 解析
ping container2
nslookup container2
# 測試連接
curl http://container2:8080
# 測試 port 是否開啟
telnet container2 8080
nc -zv container2 8080
3. 查看網路流量
# 在宿主機上監聽 docker0
tcpdump -i docker0
# 監聽特定容器的網路介面
docker exec container1 tcpdump -i eth0
# 使用 nethogs 監控容器流量
nethogs docker0
4. 常見問題
問題 1:容器無法連接外部網路
檢查:
# 檢查容器內的路由
docker exec container1 ip route
# 檢查 DNS
docker exec container1 cat /etc/resolv.conf
# 測試外部連接
docker exec container1 ping 8.8.8.8
解決:
# 重建網路
docker network rm my-net
docker network create my-net
# 或檢查防火牆設定
iptables -L -n
問題 2:容器名稱無法解析
原因:使用預設 bridge 網路
解決:
# 建立自訂網路
docker network create my-net
# 重新啟動容器並加入自訂網路
docker run -d --name db --network my-net postgres
docker run -d --name api --network my-net myapi
問題 3:Port 映射不生效
檢查:
# 檢查 port 映射
docker port <container>
# 檢查容器內服務是否監聽正確的 port
docker exec container1 netstat -tlnp
注意:
- 容器內服務要監聽
0.0.0.0,不是127.0.0.1 - 防火牆可能阻擋連接
問題 4:無法刪除網路
錯誤:
Error response from daemon: network my-net has active endpoints
解決:
# 查看哪些容器連接到此網路
docker network inspect my-net --format='{{range .Containers}}{{.Name}} {{end}}'
# 斷開所有容器
docker network disconnect my-net container1
docker network disconnect my-net container2
# 或停止使用此網路的容器
docker stop container1 container2
# 然後刪除網路
docker network rm my-net
5. 網路效能測試
# 使用 iperf3 測試網路效能
# 在容器1啟動伺服器
docker run -d --name server --network my-net networkstatic/iperf3 -s
# 在容器2測試
docker run --rm --network my-net networkstatic/iperf3 -c server
Docker Network 與 Docker Compose
預設行為
Docker Compose 會自動建立一個網路,所有服務都加入此網路。
version: '3.8'
services:
web:
image: nginx
api:
image: myapi
db:
image: postgres
# Compose 自動建立:<project-name>_default 網路
自訂多個網路
version: '3.8'
services:
web:
image: nginx
networks:
- frontend
ports:
- "80:80"
api:
image: myapi
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 禁止外部存取
總結
網路類型選擇
| 使用情境 | 推薦類型 | 原因 |
|---|---|---|
| 單機多容器 | Bridge (自訂) | 支援容器名稱解析 |
| 需要最高效能 | Host | 無網路轉換 |
| 完全隔離 | None | 無網路存取 |
| 跨主機通訊 | Overlay | 支援分散式 |
| 容器需要在區域網路可見 | Macvlan | 獨立 MAC 位址 |
核心原則
- 使用自訂網路:提供容器名稱解析
- 網路隔離:前端/後端分離
- 最小權限:只暴露必要的 port
- 命名規範:使用有意義的網路名稱
- 定期清理:移除未使用的網路
常用指令速查
# 列出網路
docker network ls
# 建立網路
docker network create my-net
# 查看網路詳細資訊
docker network inspect my-net
# 連接容器到網路
docker network connect my-net container1
# 斷開容器與網路
docker network disconnect my-net container1
# 刪除網路
docker network rm my-net
# 清理未使用的網路
docker network prune
建立日期:2025-11-03