Docker 网络管理

一、Docker 网络概述

1.1 什么是 Docker 网络

Docker 网络是容器之间、容器与宿主机之间、容器与外部网络之间通信的基础设施。Docker 在安装时会自动创建三种默认网络,并提供多种网络驱动以满足不同场景需求。

1.2 Docker 网络的核心作用

作用 说明
容器间通信 同一宿主机上不同容器之间的互联互通
容器与外部通信 容器访问互联网或外部服务
外部访问容器 通过端口映射将容器服务暴露给外部用户
网络隔离 不同网络间的容器相互隔离,提升安全性
服务发现 容器可以通过名称互相访问(自定义网络)

1.3 查看 Docker 网络

# 查看所有网络
docker network ls

# 输出示例
NETWORK ID     NAME      DRIVER    SCOPE
c8e6b7d9f1a2   bridge    bridge    local
a1b2c3d4e5f6   host      host      local
f6e5d4c3b2a1   none      null      local

二、五种网络驱动详解

Docker 提供 5 种网络驱动,每种适用于不同场景:

驱动 说明 适用场景
bridge 默认网络驱动,容器通过 Docker 网桥通信 单机容器通信(默认)
host 容器直接使用宿主机网络栈 高性能场景、端口固定
overlay 跨主机容器通信(Swarm/Kubernetes) 多机集群
macvlan 容器拥有独立 MAC 地址,直连物理网络 需要直接暴露到物理网络
none 无网络,完全隔离 安全要求极高、不需要网络

2.1 bridge(桥接网络)

原理:Docker 在宿主机创建一个虚拟网桥 docker0,每个容器通过 veth pair 连接到该网桥,容器间通过网桥通信。

宿主机
┌─────────────────────────────────────────────────────────────────┐
│  ┌─────────────┐         ┌─────────────┐                     │
│  │  容器 A      │         │  容器 B      │                     │
│  │  eth0        │         │  eth0        │                     │
│  │  172.17.0.2  │         │  172.17.0.3  │                     │
│  └──────┬──────┘         └──────┬──────┘                     │
│         │ veth pair             │ veth pair                    │
│         └───────────┬───────────┘                             │
│                     ▼                                         │
│              ┌──────────────┐                                  │
│              │  docker0     │ ← 虚拟网桥                       │
│              │  172.17.0.1  │                                  │
│              └──────────────┘                                  │
│                     │                                          │
│              ┌──────┴──────┐                                   │
│              │  宿主机网卡   │                                   │
│              └─────────────┘                                   │
└─────────────────────────────────────────────────────────────────┘

常用命令

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

# 创建自定义 bridge 网络(推荐)
docker network create --driver bridge my-net

# 运行容器时指定网络
docker run -d --name myapp --network my-net nginx

默认 bridge vs 自定义 bridge

对比项 默认 bridge 自定义 bridge
容器间 DNS 解析 不支持(需用 IP) 支持容器名解析
网络隔离 所有容器都在同一网络 可创建多个隔离网络
容器热插拔 需重启容器 可动态连接/断开
配置灵活性

2.2 host(主机网络)

原理:容器直接使用宿主机网络栈,不进行网络隔离,容器端口直接绑定到宿主机。

# 使用 host 网络
docker run -d --network host --name myapp nginx

# 此时容器中的 nginx 直接使用宿主机的 80 端口
# 访问 http://宿主机IP:80 即可访问容器服务

优点
- 性能接近原生(无 NAT 转换)
- 端口无需手动映射

缺点
- 无网络隔离,容器与宿主机共享端口空间
- 不同容器的端口不能冲突

适用场景
- 对网络性能要求极高的服务
- 需要固定端口的场景
- 监控工具(如 Prometheus Node Exporter)

2.3 overlay(覆盖网络)

原理:通过 VXLAN 隧道技术,让不同宿主机上的容器像在同一网络中通信。

适用场景:Docker Swarm、Kubernetes 集群跨主机通信。

# 创建 overlay 网络(需要 Swarm 模式)
docker network create -d overlay my-overlay

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

2.4 macvlan(MAC 地址网络)

原理:为容器分配独立的 MAC 地址,容器直接连接到物理网络,像独立物理机一样。

# 创建 macvlan 网络
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

适用场景:传统应用迁移、需要网络流量监控的场景。

2.5 none(无网络)

原理:容器没有网络接口,完全隔离。

docker run -d --network none --name isolated nginx

适用场景
- 不需要网络的批处理任务
- 安全性要求极高的服务
- 离线数据处理

三、容器网络通信模式

3.1 容器间通信

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

# 启动两个容器在同一网络
docker run -d --name web --network app-net nginx
docker run -d --name redis --network app-net redis

# 通过容器名互相访问(DNS 自动解析)
docker exec web ping redis        # 成功
docker exec web curl http://redis:6379  # 成功

3.2 容器访问外网

默认情况下,容器通过 NAT 访问外网:

# 容器内可以 ping 通外网
docker exec web ping 8.8.8.8
docker exec web curl https://www.baidu.com

3.3 外网访问容器(端口映射)

# 端口映射格式:-p 宿主机端口:容器端口
docker run -d -p 8080:80 --name web nginx

# 访问 http://宿主机IP:8080 即可访问 nginx

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

# 随机端口映射
docker run -d -P nginx  # 宿主机随机分配端口

# 只绑定到特定 IP
docker run -d -p 127.0.0.1:8080:80 nginx

3.4 端口映射查看

# 查看端口映射
docker port web

# 输出示例
80/tcp -> 0.0.0.0:8080
443/tcp -> 0.0.0.0:8443

# 查看所有容器端口映射
docker ps --format "table {{.Names}}\t{{.Ports}}"

四、自定义网络

4.1 创建自定义网络

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

# 创建带子网配置的网络
docker network create \
  --driver bridge \
  --subnet=10.10.0.0/16 \
  --gateway=10.10.0.1 \
  --ip-range=10.10.1.0/24 \
  my-custom-net

# 带标签
docker network create --label env=prod my-prod-net

4.2 连接/断开容器

# 启动时指定网络
docker run -d --name web --network my-net nginx

# 运行时连接网络
docker network connect my-net web

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

# 查看容器网络详情
docker inspect web

4.3 删除网络

# 删除网络(需先断开所有容器)
docker network rm my-net

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

五、网络排障命令

5.1 查看网络详情

# 查看网络列表
docker network ls

# 查看网络详情(包括连接的容器)
docker network inspect bridge

# 查看容器网络配置
docker inspect web | grep -A 10 "Networks"

5.2 网络诊断工具

# 进入容器进行网络测试
docker exec -it web /bin/bash

# 在容器内
ping 172.17.0.3          # 测试 IP 连通性
curl http://redis:6379   # 测试服务
nslookup redis           # DNS 解析测试
ip addr show             # 查看容器 IP
route -n                 # 查看路由表

5.3 常见问题排查

# 查看容器 IP
docker inspect web | grep IPAddress

# 查看宿主机网桥配置
ip addr show docker0
brctl show docker0

# 查看 iptables 规则(端口映射由 NAT 实现)
iptables -t nat -L -n

# 查看网络连接跟踪
conntrack -L | grep 172.17

六、Docker Compose 网络

6.1 默认网络

version: '3.8'
services:
  web:
    image: nginx
  redis:
    image: redis

Compose 会创建名为 项目名_default 的网络,所有服务自动加入,可通过服务名互相访问。

6.2 自定义网络

version: '3.8'
services:
  web:
    image: nginx
    networks:
      - frontend
  api:
    image: myapp
    networks:
      - frontend
      - backend
  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

6.3 预定义网络(外部网络)

version: '3.8'
services:
  web:
    image: nginx
    networks:
      - my-existing-net

networks:
  my-existing-net:
    external: true

七、网络性能优化

7.1 性能对比

网络模式 性能 延迟 适用场景
host 最高 最低 高性能场景
bridge(自定义) 较高 一般生产
bridge(默认) 一般 测试开发
overlay 较低 跨主机通信

7.2 优化建议

# 1. 使用自定义 bridge 而非默认 bridge
docker network create my-net

# 2. 禁用 IP 转发(仅容器间通信,无需外网)
sysctl -w net.ipv4.ip_forward=0

# 3. 调整 docker0 网桥 MTU
# 修改 /etc/docker/daemon.json
{
  "mtu": 1400
}

7.3 监控网络流量

# 查看容器网络流量
docker stats --no-stream

# 查看容器网络 I/O
docker inspect web | grep -A 5 "NetworkSettings"

# 使用 iftop 监控(需安装)
docker exec web iftop -i eth0

八、网络配置持久化

8.1 /etc/docker/daemon.json 配置

{
  "bip": "172.20.0.1/16",              // 网桥 IP
  "fixed-cidr": "172.20.10.0/24",      // 容器 IP 范围
  "default-address-pools": [
    {
      "base": "172.20.0.0/16",
      "size": 24
    }
  ],
  "mtu": 1400,
  "iptables": true,
  "ip-forward": true
}

8.2 重启网络配置

# 修改配置后重启 Docker
sudo systemctl restart docker

# 重启后需重建自定义网络
docker network prune

九、最佳实践

9.1 网络设计原则

原则 说明
分类隔离 不同环境(dev/test/prod)使用不同网络
按功能划分 前端网络、后端网络、数据库网络分层隔离
自定义网络 不使用默认 bridge,创建自定义网络
固定子网 生产环境规划好子网范围,避免 IP 冲突

9.2 安全建议

# 1. 容器只连接需要的网络
docker network connect frontend web
docker network connect backend api

# 2. 敏感服务不暴露端口
docker run -d --network backend --name db mysql

# 3. 使用防火墙限制访问
iptables -A DOCKER -p tcp --dport 8080 -s 192.168.1.0/24 -j ACCEPT

9.3 多环境网络隔离

# 创建不同环境的网络
docker network create dev-net
docker network create test-net
docker network create prod-net

# 不同环境使用不同网络实现隔离
docker run -d --network dev-net --name app-dev myapp:dev
docker run -d --network test-net --name app-test myapp:test

9.4 网络资源清理

# 清理未使用的网络
docker network prune

# 清理所有未使用的网络(不提示)
docker network prune -f

# 查看网络占用
docker network ls
docker network inspect <network> | grep -c "Container"

十、命令速查表

操作 命令
查看网络列表 docker network ls
查看网络详情 docker network inspect <网络名>
创建 bridge 网络 docker network create <网络名>
创建带子网的网络 docker network create --subnet=10.0.0.0/24 <网络名>
删除网络 docker network rm <网络名>
清理未使用网络 docker network prune
连接容器到网络 docker network connect <网络名> <容器名>
断开容器与网络 docker network disconnect <网络名> <容器名>
端口映射 -p 宿主机端口:容器端口
随机端口映射 -P
使用 host 网络 --network host
使用 none 网络 --network none
查看容器 IP docker inspect <容器名> \| grep IPAddress
查看端口映射 docker port <容器名>

十一、总结

Docker 网络五驱动
- bridge:单机默认,容器间通信(最常用)
- host:性能最佳,与宿主机共享网络
- overlay:跨主机通信,Swarm/K8s 用
- macvlan:直连物理网络,独立 MAC
- none:完全隔离,安全场景

生产建议:使用自定义 bridge 网络实现容器间 DNS 解析,按环境/功能划分网络实现隔离,敏感服务不暴露端口,非必要不用 --network host