强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Docker 完全指南 / 07 - 网络模型

07 - 网络模型

理解 Docker 的网络模式、容器间通信、端口映射与自定义网络配置。


7.1 Docker 网络基础

Docker 容器默认是网络隔离的,每个容器拥有独立的网络命名空间(Network Namespace)。

容器网络全景:
  ┌─────────────────────────────────────────────┐
  │                 宿主机 (Host)                 │
  │                                              │
  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
  │  │ 容器 A   │  │ 容器 B   │  │ 容器 C   │  │
  │  │ 172.17   │  │ 172.17   │  │ 172.18   │  │
  │  │ .0.2     │  │ .0.3     │  │ .0.2     │  │
  │  └────┬─────┘  └────┬─────┘  └────┬─────┘  │
  │       │              │              │        │
  │  ┌────┴──────────────┴───┐   ┌─────┴─────┐ │
  │  │    docker0 (bridge)   │   │  my-net   │ │
  │  │      172.17.0.1       │   │ 172.18.0.1│ │
  │  └───────────┬───────────┘   └─────┬─────┘ │
  │              │                      │       │
  │         ┌────┴──────────────────────┴──┐    │
  │         │        NAT / iptables        │    │
  │         └────────────┬─────────────────┘    │
  │                      │                      │
  │                  物理网卡 eth0              │
  └──────────────────────┬──────────────────────┘
                      Internet

7.2 网络驱动类型

驱动名称说明适用场景
bridge桥接网络默认模式,容器通过虚拟网桥通信单机多容器
host主机网络容器直接使用宿主机网络栈高性能需求
overlay覆盖网络跨主机容器通信Swarm/K8s 集群
macvlanMAC 地址分配容器拥有独立 MAC 地址需要直连物理网络
none无网络完全禁用网络安全隔离场景

7.3 Bridge 网络(默认)

默认 bridge 网络

默认 bridge 网络:
  ┌─────────────────────────────────────────────┐
  │                 宿主机                       │
  │                                              │
  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
  │  │ 容器 A   │  │ 容器 B   │  │ 容器 C   │  │
  │  │ eth0     │  │ eth0     │  │ eth0     │  │
  │  │172.17.0.2│  │172.17.0.3│  │172.17.0.4│  │
  │  └────┬─────┘  └────┬─────┘  └────┬─────┘  │
  │       │   veth-pair  │   veth-pair  │        │
  │  ┌────┴──────────────┴──────────────┴───┐   │
  │  │         docker0 (172.17.0.1)         │   │
  │  └──────────────────┬───────────────────┘   │
  │                     │ NAT                    │
  │                 物理网卡                     │
  └─────────────────────┬───────────────────────┘
                     Internet
# 查看默认 bridge 网络
docker network ls

# 查看 bridge 网络详情
docker network inspect bridge

# 在默认 bridge 中运行容器
docker run -d --name web1 nginx:alpine
docker run -d --name web2 nginx:alpine

# 查看容器 IP
docker inspect --format '{{.NetworkSettings.IPAddress}}' web1
# 172.17.0.2

# 容器间通过 IP 通信
docker exec web1 ping 172.17.0.3

用户自定义 bridge 网络(推荐)

# 创建自定义 bridge 网络
docker network create my-net

# 创建指定子网和网关的网络
docker network create \
    --driver bridge \
    --subnet 192.168.100.0/24 \
    --gateway 192.168.100.1 \
    my-custom-net

# 在自定义网络中运行容器
docker run -d --name app --network my-net nginx:alpine
docker run -d --name db --network my-net postgres:16

# 自定义网络支持 DNS 解析(容器名即域名)
docker exec app ping db       # ✅ 可以通过容器名解析
docker exec app ping db.my-net  # 也可以用完整域名

默认 bridge vs 自定义 bridge

特性默认 bridge自定义 bridge
DNS 解析❌ 仅用 IP✅ 容器名即域名
自动连接✅ 新容器自动加入❌ 需指定 --network
网络隔离所有容器共享按网络分组隔离
配置灵活性有限可自定义子网、网关等
推荐场景临时测试生产环境推荐

7.4 端口映射(Port Mapping)

基本语法

# 映射单个端口
docker run -d -p 8080:80 nginx:alpine
# 宿主机 8080 → 容器 80

# 映射多个端口
docker run -d -p 8080:80 -p 8443:443 nginx:alpine

# 指定绑定地址
docker run -d -p 127.0.0.1:8080:80 nginx:alpine
# 仅本机可访问

# 映射 UDP 端口
docker run -d -p 5353:53/udp dns-server:latest

# 随机分配宿主机端口
docker run -d -p 80 nginx:alpine

# 映射端口范围
docker run -d -p 8080-8085:80-85 my-app:latest

# 查看端口映射
docker port my-container
# 80/tcp -> 0.0.0.0:8080

端口映射原理

端口映射的底层机制 (iptables NAT):

  外部请求 → 宿主机:8080
    ↓ iptables DNAT 规则
  转发 → 172.17.0.2:80 (容器)
    ↓ 容器处理请求
  响应 → 原路返回

查看 iptables 规则:
  sudo iptables -t nat -L -n | grep 8080

7.5 Host 网络

# 使用 host 网络模式
docker run -d --network host nginx:alpine

# 容器直接使用宿主机网络,无需 -p 映射端口
# 容器内监听 80 端口 = 宿主机 80 端口
Host 网络模式:
  ┌──────────────────────────────┐
  │         宿主机网络栈          │
  │  eth0: 192.168.1.100        │
  │  ┌──────────────────────┐   │
  │  │  容器 (共享网络栈)    │   │
  │  │  nginx 监听 :80      │   │
  │  │  = 宿主机 :80        │   │
  │  └──────────────────────┘   │
  └──────────────────────────────┘
优势劣势
最高网络性能(无 NAT 开销)端口冲突风险
无需端口映射失去网络隔离
延迟最低无法限制容器网络访问

适用场景:对网络性能要求极高的场景,如监控 Agent、日志收集器。


7.6 None 网络

# 完全禁用网络
docker run -d --network none alpine:latest sleep 3600

# 验证:容器没有网络接口
docker exec <container_id> ip addr
# 只有 lo (loopback) 接口

适用场景:安全敏感的任务,如密码处理、密钥生成等。


7.7 Overlay 网络(跨主机通信)

Overlay 网络用于 Docker Swarm 集群中跨主机的容器通信。

Overlay 网络:
  ┌──────────── Host A ────────────┐  ┌──────────── Host B ────────────┐
  │                                │  │                                │
  │  ┌──────────┐  ┌──────────┐  │  │  ┌──────────┐                  │
  │  │ 容器 1   │  │ 容器 2   │  │  │  │ 容器 3   │                  │
  │  │10.0.0.2  │  │10.0.0.3  │  │  │  │10.0.0.4  │                  │
  │  └────┬─────┘  └────┬─────┘  │  │  └────┬─────┘                  │
  │       └──────┬───────┘        │  │       │                        │
  │         overlay 网络           │  │  overlay 网络                  │
  │              │                 │  │       │                        │
  │         VXLAN 隧道             │  │  VXLAN 隧道                   │
  └──────────────┼────────────────┘  └────────┼────────────────────────┘
                 └────────────────────────────┘
                      物理网络
# 初始化 Swarm(必要前提)
docker swarm init

# 创建 overlay 网络
docker network create --driver overlay my-overlay

# 创建可被外部容器加入的 overlay 网络
docker network create --driver overlay --attachable my-attachable

# 在 Swarm 服务中使用
docker service create --name web --network my-overlay --replicas 3 nginx:alpine

7.8 Macvlan 网络

Macvlan 让容器拥有独立的 MAC 和 IP 地址,直接出现在物理网络上。

# 创建 macvlan 网络
docker network create -d macvlan \
    --subnet=192.168.1.0/24 \
    --gateway=192.168.1.1 \
    -o parent=eth0 \
    my-macvlan

# 运行容器并分配静态 IP
docker run -d --name mv-web \
    --network my-macvlan \
    --ip 192.168.1.100 \
    nginx:alpine
特性macvlanbridge
独立 IP✅ 物理网络分配虚拟子网
独立 MAC
性能接近原生有 NAT 开销
跨主机通信✅ 无需 VXLAN需要 overlay
使用难度较高简单

7.9 容器间通信

同一网络内通信

# 创建网络
docker network create app-net

# 运行应用容器和数据库容器
docker run -d --name app --network app-net my-app:v1
docker run -d --name db --network app-net -e POSTGRES_PASSWORD=secret postgres:16

# 容器间通过容器名通信
docker exec app ping db
docker exec app curl http://db:5432

跨网络通信

# 容器连接到多个网络
docker network create frontend
docker network create backend

docker run -d --name api --network frontend my-api:v1
docker run -d --name db --network backend postgres:16

# 将 API 容器连接到 backend 网络
docker network connect backend api

# 现在 api 可以访问 db
docker exec api ping db

# 断开网络
docker network disconnect backend api
多网络连接:
  ┌──────────────────────────────────┐
  │  宿主机                           │
  │                                   │
  │  ┌──────────────────────────┐    │
  │  │      API 容器             │    │
  │  │  eth0: frontend 网络     │    │
  │  │  eth1: backend 网络      │    │
  │  └────┬────────────┬────────┘    │
  │       │            │              │
  │  ┌────┴────┐  ┌────┴─────┐      │
  │  │frontend │  │ backend  │      │
  │  │ 网络    │  │ 网络     │      │
  │  └─────────┘  └────┬─────┘      │
  │                    │              │
  │               ┌────┴────┐        │
  │               │   DB    │        │
  │               └─────────┘        │
  └──────────────────────────────────┘

7.10 DNS 与服务发现

# 自定义 DNS 服务器
docker run -d --dns 8.8.8.8 --dns 114.114.114.114 nginx:alpine

# 添加 DNS 搜索域
docker run -d --dns-search example.com nginx:alpine

# 添加 hosts 记录
docker run -d --add-host myhost:192.168.1.100 nginx:alpine
docker run -d --add-host host.docker.internal:host-gateway nginx:alpine

Docker 内置 DNS

Docker 内嵌 DNS 服务器 (127.0.0.11):

  容器 A (app) 请求 "db"
  Docker DNS (127.0.0.11)
  解析为同一网络中的 db 容器 IP
  返回 172.18.0.3

7.11 网络管理命令

# 列出所有网络
docker network ls

# 查看网络详情
docker network inspect my-net

# 创建网络
docker network create \
    --driver bridge \
    --subnet 10.10.0.0/16 \
    --ip-range 10.10.1.0/24 \
    --opt "com.docker.network.bridge.name"="br-custom" \
    custom-net

# 连接容器到网络
docker network connect my-net my-container

# 指定 IP 连接
docker network connect --ip 10.10.1.100 my-net my-container

# 断开网络
docker network disconnect my-net my-container

# 删除网络
docker network rm my-net

# 删除所有未使用的网络
docker network prune

# 删除指定时间前的未使用网络
docker network prune --filter "until=24h"

7.12 高级网络配置

自定义 docker0 网桥

// /etc/docker/daemon.json
{
  "bip": "10.0.0.1/16",
  "fixed-cidr": "10.0.0.0/16",
  "default-address-pools": [
    { "base": "172.20.0.0/14", "size": 24 }
  ]
}

容器内抓包调试

# 获取容器的 namespace PID
PID=$(docker inspect --format '{{.State.Pid}}' my-container)

# 使用 nsenter 在容器网络中抓包
sudo nsenter -t $PID -n tcpdump -i eth0 -w /tmp/capture.pcap

# 或者在容器内安装 tcpdump
docker exec my-container apk add tcpdump
docker exec my-container tcpdump -i eth0 -c 10

要点回顾

要点核心内容
网络模式bridge(默认)、host、overlay、macvlan、none
自定义网络推荐使用自定义 bridge,支持 DNS 容器名解析
端口映射-p 宿主机端口:容器端口,注意安全暴露
服务发现Docker 内置 DNS,容器名即域名
多网络容器可连接多个网络,实现网络分层隔离

注意事项

端口安全: -p 0.0.0.0:8080:80 会将端口暴露给所有网络接口。生产环境建议限制绑定地址(如 -p 127.0.0.1:8080:80)。

bridge 网络性能: bridge 模式有 NAT 开销。对延迟敏感的应用可考虑 host 模式。

Overlay 网络: 需要额外的 VXLAN 封装开销,且需要开放 UDP 4789 端口。


下一步

08 - 数据持久化:学习 Docker 卷和数据管理策略。