Skip to content

Docker 网络配置详解 ​

Docker 网络是容器化应用的核心组件之一,它决定了容器之间以及容器与外部世界如何通信。本文将深入讲解 Docker 的各种网络模式、配置方法和最佳实践。

目录 ​

  1. Docker 网络基础
  2. 网络模式详解
  3. Bridge 网络
  4. Host 网络
  5. Overlay 网络
  6. 端口映射
  7. 自定义网络
  8. 容器 DNS 配置
  9. 网络安全

Docker 网络基础 ​

1.1 网络架构概览 ​

Docker 使用可插拔的网络架构,支持多种网络驱动:

┌─────────────────────────────────────────────────────────────┐
│                        Docker Host                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                 docker0 (网桥)                       │   │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐             │   │
│  │  │Container│  │Container│  │Container│             │   │
│  │  │  eth0   │  │  eth0   │  │  eth0   │             │   │
│  │  └───┬─────┘  └────┬────┘  └────┬────┘             │   │
│  │      └─────────────┴────────────┘                   │   │
│  │              veth pair (虚拟以太网对)                │   │
│  └─────────────────────────────────────────────────────┘   │
│                          │                                  │
│                    NAT/iptables                            │
│                          │                                  │
│                    物理网络接口                             │
└─────────────────────────────────────────────────────────────┘

1.2 默认网络 ​

安装 Docker 后,会自动创建三个默认网络:

bash
# 查看默认网络
docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
1234567890ab   bridge    bridge    local
2345678901bc   host      host      local
3456789012cd   none      null      local
网络名称驱动说明
bridgebridge默认网络,容器通过网桥通信
hosthost容器共享主机网络栈
nonenull容器无网络接口

1.3 网络驱动类型 ​

驱动用途适用场景
bridge单机容器通信单主机部署
host主机网络共享高性能网络需求
overlay跨主机通信Swarm 集群
macvlanMAC 地址分配需要独立 IP
ipvlanIPv4/IPv6 管理高级网络场景
none禁用网络完全隔离

网络模式详解 ​

2.1 Bridge 模式(默认) ​

Bridge 是 Docker 的默认网络模式,容器通过虚拟网桥 docker0 进行通信。

bash
# 查看网桥信息
ip addr show docker0

# 查看网桥详情
brctl show docker0

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

容器网络配置示例:

bash
# 运行容器并查看网络配置
docker run -d --name web nginx:alpine

# 查看容器网络信息
docker inspect web --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'

# 进入容器查看网络
docker exec web ip addr

2.2 Host 模式 ​

Host 模式下,容器直接使用主机的网络栈,不获得独立的 IP 地址。

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

# 容器将直接使用主机的 80 端口
# 无需端口映射

Host 模式特点:

特性说明
性能无 NAT 开销,性能最好
端口冲突容器端口不能与主机冲突
隔离性网络隔离性最低
适用场景高性能网络应用、网络诊断工具

2.3 None 模式 ​

None 模式下,容器只有 loopback 接口,完全隔离网络。

bash
# 使用 none 网络模式
docker run -d --name isolated --network none alpine sleep 3600

# 验证网络隔离
docker exec isolated ip addr
# 只显示 lo 接口

2.4 Container 模式 ​

Container 模式让新容器共享另一个容器的网络命名空间。

bash
# 创建基础容器
docker run -d --name base nginx:alpine

# 创建共享网络的容器
docker run -d --name sidecar --network container:base alpine sleep 3600

# 两个容器共享相同的网络接口

Bridge 网络 ​

3.1 默认 Bridge 网络 ​

bash
# 查看默认网桥配置
docker network inspect bridge

# 查看容器连接信息
docker network inspect bridge --format='{{json .Containers}}'

默认网桥的限制:

  • 容器间只能通过 IP 地址通信
  • 不支持自动服务发现
  • 不支持自定义 DNS

3.2 自定义 Bridge 网络 ​

创建自定义网桥网络:

bash
# 创建自定义网络
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  --opt com.docker.network.bridge.name=my-bridge \
  my-network

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

在自定义网络中运行容器:

bash
# 运行容器并连接到自定义网络
docker run -d --name web --network my-network nginx:alpine
docker run -d --name db --network my-network postgres:15-alpine

# 容器间可以通过名称通信
docker exec web ping db

3.3 多网络连接 ​

一个容器可以连接到多个网络:

bash
# 创建多个网络
docker network create frontend
docker network create backend

# 运行容器连接到 frontend
docker run -d --name app --network frontend nginx:alpine

# 连接到额外的网络
docker network connect backend app

# 查看容器的所有网络连接
docker inspect app --format='{{range $key, $value := .NetworkSettings.Networks}}{{$key}} {{end}}'

Host 网络 ​

4.1 使用场景 ​

bash
# 高性能网络应用
docker run -d --network host \
  --name high-performance-app \
  myapp:latest

# 网络诊断工具
docker run --rm --network host \
  nicolaka/netshoot \
  tcpdump -i eth0

4.2 Host 模式注意事项 ​

bash
# 查看主机端口使用情况
netstat -tlnp

# Host 模式下容器端口直接绑定到主机
# 需要确保端口不冲突

Overlay 网络 ​

5.1 Swarm 模式下的 Overlay ​

Overlay 网络用于跨主机的容器通信,需要 Docker Swarm 模式。

bash
# 初始化 Swarm
docker swarm init

# 创建 Overlay 网络
docker network create \
  --driver overlay \
  --subnet 10.0.0.0/16 \
  --attachable \
  my-overlay

# 创建使用 Overlay 网络的服务
docker service create \
  --name web \
  --network my-overlay \
  --replicas 3 \
  nginx:alpine

5.2 Overlay 网络加密 ​

bash
# 创建加密的 Overlay 网络
docker network create \
  --driver overlay \
  --opt encrypted \
  --subnet 10.0.0.0/16 \
  secure-overlay

5.3 Overlay 网络架构 ​

┌─────────────────────┐         ┌─────────────────────┐
│    Docker Host 1    │         │    Docker Host 2    │
│  ┌───────────────┐  │         │  ┌───────────────┐  │
│  │   Container   │  │         │  │   Container   │  │
│  │   10.0.0.2    │  │◄───────►│  │   10.0.0.3    │  │
│  └───────┬───────┘  │  VXLAN  │  └───────┬───────┘  │
│          │          │  Tunnel │          │          │
│  ┌───────▼───────┐  │         │  ┌───────▼───────┐  │
│  │   VXLAN       │  │◄───────►│  │   VXLAN       │  │
│  │   Interface   │  │         │  │   Interface   │  │
│  └───────────────┘  │         │  └───────────────┘  │
└─────────────────────┘         └─────────────────────┘

端口映射 ​

6.1 基本端口映射 ​

bash
# 映射单个端口
docker run -d -p 8080:80 nginx:alpine

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

# 映射到随机主机端口
docker run -d -p 80 nginx:alpine

# 查看映射的端口
docker port <container-id>

6.2 高级端口映射 ​

bash
# 指定绑定地址
docker run -d -p 127.0.0.1:8080:80 nginx:alpine

# 指定协议
docker run -d -p 8080:80/udp nginx:alpine

# 映射端口范围
docker run -d -p 8000-8010:8000-8010 nginx:alpine

# 使用主机网络接口
docker run -d -p 192.168.1.100:8080:80 nginx:alpine

6.3 端口映射与防火墙 ​

bash
# 查看 Docker 创建的 iptables 规则
iptables -t nat -L DOCKER -n -v

# 查看端口转发规则
iptables -t nat -L PREROUTING -n -v | grep DOCKER

自定义网络 ​

7.1 创建高级网络配置 ​

bash
# 创建具有完整配置的网络
docker network create \
  --driver bridge \
  --subnet 192.168.100.0/24 \
  --gateway 192.168.100.1 \
  --ip-range 192.168.100.128/25 \
  --ipv6 \
  --subnet fd00:dead:beef::/48 \
  --label environment=production \
  --label project=myapp \
  --opt com.docker.network.bridge.name=br-custom \
  --opt com.docker.network.bridge.enable_icc=true \
  --opt com.docker.network.bridge.enable_ip_masquerade=true \
  --opt com.docker.network.driver.mtu=1450 \
  custom-network

7.2 网络配置选项 ​

选项说明默认值
--subnet子网 CIDR自动分配
--gateway网关 IP子网第一个地址
--ip-rangeIP 分配范围整个子网
--aux-address排除的 IP无
--opt encrypted加密流量false
--attachable允许非 Swarm 容器连接false

7.3 网络管理命令 ​

bash
# 列出所有网络
docker network ls

# 查看网络详情
docker network inspect network-name

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

# 断开容器网络连接
docker network disconnect network-name container-name

# 删除网络
docker network rm network-name

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

容器 DNS 配置 ​

8.1 默认 DNS 行为 ​

Docker 使用嵌入式 DNS 服务器(127.0.0.11)为容器提供名称解析。

bash
# 查看容器的 DNS 配置
docker run --rm alpine cat /etc/resolv.conf

# 输出示例:
# nameserver 127.0.0.11

8.2 自定义 DNS 配置 ​

bash
# 指定 DNS 服务器
docker run -d \
  --dns 8.8.8.8 \
  --dns 8.8.4.4 \
  --dns-search example.com \
  --dns-opt ndots:2 \
  nginx:alpine

8.3 Docker Compose DNS 配置 ​

yaml
version: '3.8'
services:
  web:
    image: nginx:alpine
    dns:
      - 8.8.8.8
      - 8.8.4.4
    dns_search:
      - example.com
    dns_opt:
      - ndots:2
      - timeout:2
    extra_hosts:
      - "database:192.168.1.100"
      - "cache:192.168.1.101"

8.4 服务发现 ​

在自定义网络中,容器可以通过名称相互发现:

bash
# 创建网络
docker network create my-app

# 运行服务
docker run -d --name api --network my-app myapi:latest
docker run -d --name web --network my-app myweb:latest

# 在 web 容器中可以解析 api 名称
docker exec web nslookup api

网络安全 ​

9.1 网络隔离 ​

bash
# 禁用容器间通信
docker network create \
  --opt com.docker.network.bridge.enable_icc=false \
  isolated-network

# 禁用 IP 伪装(容器无法访问外部网络)
docker network create \
  --opt com.docker.network.bridge.enable_ip_masquerade=false \
  internal-network

9.2 防火墙规则 ​

bash
# 查看 Docker 创建的规则
iptables -L DOCKER-ISOLATION-STAGE-1 -n -v
iptables -L DOCKER-ISOLATION-STAGE-2 -n -v

# 自定义容器防火墙规则
docker run -d \
  --cap-add NET_ADMIN \
  --security-opt seccomp=unconfined \
  myapp:latest

9.3 网络策略(Swarm) ​

yaml
version: '3.8'
services:
  frontend:
    image: nginx:alpine
    networks:
      - frontend-network
    deploy:
      placement:
        constraints:
          - node.role == worker

  backend:
    image: myapi:latest
    networks:
      - frontend-network
      - backend-network
    deploy:
      placement:
        constraints:
          - node.role == worker

  database:
    image: postgres:15-alpine
    networks:
      - backend-network
    deploy:
      placement:
        constraints:
          - node.role == manager

networks:
  frontend-network:
    driver: overlay
    internal: false
  backend-network:
    driver: overlay
    internal: true  # 无外部访问

故障排查 ​

10.1 网络诊断工具 ​

bash
# 使用 netshoot 进行网络诊断
docker run --rm --network container:target-container \
  nicolaka/netshoot \
  tcpdump -i eth0

# 常用诊断命令
docker run --rm --network container:target nicolaka/netshoot dig google.com
docker run --rm --network container:target nicolaka/netshoot traceroute 8.8.8.8
docker run --rm --network container:target nicolaka/netshoot curl -v http://service

10.2 常见问题 ​

bash
# 容器无法访问外部网络
# 检查 IP 转发
sysctl net.ipv4.ip_forward

# 检查 NAT 规则
iptables -t nat -L POSTROUTING -n -v

# 容器间无法通信
# 检查是否在同一网络
docker inspect container1 --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'
docker inspect container2 --format='{{range $k, $v := .NetworkSettings.Networks}}{{$k}} {{end}}'

# DNS 解析失败
# 检查 DNS 配置
docker run --rm alpine nslookup google.com
docker run --rm --dns 8.8.8.8 alpine nslookup google.com

10.3 网络重置 ​

bash
# 停止 Docker
systemctl stop docker

# 清理网络配置
iptables -t nat -F
iptables -F DOCKER
ip link del docker0

# 重启 Docker
systemctl start docker

下一步 ​

基于 MIT 许可发布