Docker Network 完全指南

深入理解 Docker 網路的運作原理、網路驅動類型、容器間通訊機制


目錄


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 位址

核心原則

  1. 使用自訂網路:提供容器名稱解析
  2. 網路隔離:前端/後端分離
  3. 最小權限:只暴露必要的 port
  4. 命名規範:使用有意義的網路名稱
  5. 定期清理:移除未使用的網路

常用指令速查

# 列出網路
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

🔗相關文章