Skip to content
Docker 网络

Docker 网络

Docker 的网络子系统负责容器之间、容器与宿主机之间、容器与外部世界之间的通信。


网络驱动概览

驱动 默认 隔离性 适用场景
bridge ✅ 宿主机内部 单机容器间通信
host — 无隔离 高性能网络需求
none — 完全隔离 无需网络的容器
overlay — 跨宿主机 Swarm 多机通信
macvlan — 物理网络级 容器直接接入物理网络
ipvlan — 物理网络级 替代 macvlan(少 MAC 限制)

bridge — 桥接模式

默认 bridge

# 不指定网络时,容器使用默认 bridge(docker0)
docker run -d --name c1 nginx
docker run -d --name c2 nginx
┌──────────────────────────────────────┐
│              宿主机                  │
│  ┌─────────┐    ┌─────────┐         │
│  │ 容器 c1  │    │ 容器 c2  │         │
│  │172.17.0.2│    │172.17.0.3│         │
│  └────┬─────┘    └────┬─────┘         │
│       └───────┬───────┘               │
│         ┌─────▼──────┐                │
│         │  docker0   │ ← 虚拟网桥     │
│         │ 172.17.0.1 │                │
│         └─────┬──────┘                │
│         ┌─────▼──────┐                │
│         │ iptables   │ ← NAT         │
│         │ (DNAT/SNAT)│                │
│         └─────┬──────┘                │
│         ┌─────▼──────┐                │
│         │    eth0    │ ← 物理网卡     │
│         └────────────┘                │
└──────────────────────────────────────┘

🚨 默认 bridge 的限制:容器之间只能通过 IP 通信,不能通过容器名 DNS 解析。需要 DNS 的服务发现应使用自定义 bridge 网络。

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

docker network create --driver bridge my_bridge

# 创建时指定子网
docker network create \
  --driver bridge \
  --subnet=192.168.100.0/24 \
  --gateway=192.168.100.1 \
  my_bridge

docker run -d --name web --network my_bridge nginx
docker run -d --name api --network my_bridge my_api

🔬 深入原理:自定义 bridge 网络相比默认 bridge 的核心区别:

特性 默认 bridge 自定义 bridge
DNS 解析(容器名) ❌ 不支持 ✅ 支持
容器互联(–link) 需要手动 自动
网络配置 固定 可自定义子网/网关/IP
隔离性 所有容器共享 按网络隔离

容器连接/断开网络

# 将运行中的容器连接到网络
docker network connect my_bridge web

# 连接时指定 IP
docker network connect --ip 192.168.100.10 my_bridge web

# 断开连接
docker network disconnect my_bridge web

💡 一个容器可以连接到多个网络,实现不同网络间的隔离访问。


host — 主机模式

docker run -d --network host nginx
不使用 namespace 隔离网络
容器直接使用宿主机的网络栈
宿主机 :80 → 容器的 80 端口(无需 -p 映射)
优缺点 说明
✅ 性能最高 无 NAT 转发、无虚拟网桥开销
✅ 无需端口映射 容器端口直接暴露在宿主机上
❌ 端口冲突 容器端口占用宿主机端口
❌ 安全隔离差 容器网络和宿主机完全共享
❌ 仅 Linux Windows/Mac 不支持真正 host 模式

⚡ 性能提示:对网络延迟敏感的数据库、消息队列等场景,可考虑 host 模式。如 Redis 官方镜像在基准测试时推荐 --network host。


none — 无网络

docker run -d --network none my_app

容器没有网络接口,只有 lo 回环。适用于:

  • 批量计算任务
  • 安全隔离极高的场景
  • 不需要任何网络通信的后台任务

端口映射详解

# 基本格式:-p [宿主机IP:][宿主机端口:]容器端口[/协议]
docker run -p 8080:80 nginx                   # 0.0.0.0:8080 → 容器:80
docker run -p 127.0.0.1:8080:80 nginx         # 仅本地 8080 → 容器:80
docker run -p 53:53/udp dns_server            # UDP 端口
docker run -p 8080:80 -p 443:443 nginx        # 多个端口

# 随机端口映射(-P):将 EXPOSE 声明的端口随机映射
docker run -d -P nginx                         # EXPOSE 80 → 随机端口
docker port <container_id>                     # 查看映射结果

🔬 深入原理:端口映射通过 iptables 的 DNAT(目标地址转换)实现:

外部请求 0.0.0.0:8080
    │
    ▼
iptables DNAT: 0.0.0.0:8080 → 容器IP:80
    │
    ▼
docker-proxy 或直接 iptables 转发
    │
    ▼
容器 eth0:80

overlay — 跨主机网络(Swarm)

# 创建 overlay 网络(需要 Swarm 模式)
docker swarm init
docker network create --driver overlay --attachable my_overlay

# 创建服务跨多节点通信
docker service create --name web --network my_overlay --replicas 3 nginx
Node A: 容器 web.1 ──┐                    Node B: 容器 web.2 ──┐
                     │                                         │
               overlay 网络 (VXLAN 隧道加密)                    │
                     │                                         │
               ┌─────▼──────────────────────────────▼─────┐
               │       跨主机容器可直接通信               │
               └──────────────────────────────────────────┘

macvlan / ipvlan — 接入物理网络

macvlan

# 创建一个 macvlan 网络,容器获得独立 MAC 地址
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  my_macvlan

docker run -d --network my_macvlan --ip 192.168.1.100 nginx

容器直接接入物理网络,获得独立的 MAC 地址和 IP,看起来像一台独立的物理机。

🚨 陷阱:macvlan 模式下,宿主机本身无法直接与同一网卡的 macvlan 容器通信(Linux 内核限制)。如需宿主机和容器互通,需要创建子接口或使用 ipvlan。

ipvlan(推荐)

docker network create -d ipvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  -o ipvlan_mode=l2 \
  my_ipvlan
模式 特点
l2 二层桥接,类似 macvlan,共享宿主机 MAC(适用于 DHCP/MAC 受限环境)
l3 三层路由,需要手动添加路由(适用于大型网络、多子网)

DNS 解析机制

# 查看容器的 DNS 配置
docker exec web cat /etc/resolv.conf

# 输出示例:
# nameserver 127.0.0.11     ← Docker 内置 DNS
# options ndots:0

🔬 深入原理:Docker 内置 DNS 服务器监听 127.0.0.11:

  • 自定义网络:自动 DNS 解析,容器名和 service 名均可解析
  • 默认 bridge:不支持 DNS 解析,只能通过 --link 添加 /etc/hosts
  • 容器名解析:ping web → 127.0.0.11:53 → 返回容器 IP
  • TTL:默认由 Docker 守护进程管理,容器重建后 DNS 自动更新
# 自定义 DNS 服务器
docker run -d --dns 8.8.8.8 --dns 114.114.114.114 nginx

# 自定义搜索域
docker run -d --dns-search example.com nginx

网络调试命令

# 查看容器 IP 地址
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_id>

# 查看容器 DNS 配置
docker exec <container_id> cat /etc/resolv.conf

# 查看 iptables 规则
iptables -t nat -L -n | grep DOCKER

# 查看网桥信息
brctl show docker0
# 或
ip link show docker0

# 查看网络连接的容器
docker network inspect my_bridge

# 容器间连通性测试
docker exec web ping api
docker exec web nslookup api

网络模式总结对比

特性 bridge custom bridge host overlay macvlan
容器间 DNS ❌ ✅ N/A ✅ ❌
端口映射 需 -p 需 -p 不需要 需 -p 不需要
外部访问 NAT NAT 直接 NAT/LB 直接
性能 中等 中等 最高 较低(VXLAN) 高
跨主机 ❌ ❌ ❌ ✅ ❌
容器名解析 ❌ ✅ N/A ✅ ❌

常见陷阱

陷阱 说明 正确做法
默认 bridge 无法 DNS 容器名无法解析 使用自定义 bridge 网络
host 模式端口冲突 容器与宿主机端口冲突 注意端口规划
macvlan 宿主机不通 宿主机无法访问 macvlan 容器 使用 ipvlan 或创建子接口
忘记创建网络 启动时 --network 指向不存在的网络 先 docker network create
Compose 网络名冲突 不同项目创建同名网络 默认自动加项目前缀隔离
internal: true 误解 内部网络容器无法访问外网 根据需求选择是否启用