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 许可发布