Skip to content

Docker 网络配置

本章将深入讲解 Docker 网络的配置和管理,包括网络模式、自定义网络、服务发现、负载均衡等核心概念和实践。

Docker 网络概述

网络架构

Docker 网络基于 Linux 网络命名空间技术,为容器提供网络隔离和通信能力:

┌─────────────────────────────────────────────────────────┐
│                    主机网络                              │
├─────────────────────────────────────────────────────────┤
│  Docker 网络层                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │   bridge    │  │    host     │  │    none     │     │
│  │   网络      │  │    网络     │  │    网络     │     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
├─────────────────────────────────────────────────────────┤
│  容器网络命名空间                                        │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │  容器 A     │  │  容器 B     │  │  容器 C     │     │
│  │  eth0       │  │  eth0       │  │  (无网络)   │     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
└─────────────────────────────────────────────────────────┘

网络驱动类型

驱动类型描述使用场景
bridge默认网络驱动,创建虚拟网桥单主机容器通信
host容器直接使用主机网络高性能网络需求
none禁用容器网络安全隔离场景
overlay跨主机容器通信集群和 Swarm 模式
macvlan为容器分配 MAC 地址需要直接连接物理网络

网络基础操作

网络管理命令

bash
# 列出所有网络
docker network ls

# 查看网络详细信息
docker network inspect bridge

# 创建自定义网络
docker network create mynetwork

# 删除网络
docker network rm mynetwork

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

# 连接容器到网络
docker network connect mynetwork container_name

# 断开容器网络连接
docker network disconnect mynetwork container_name

查看容器网络信息

bash
# 查看容器网络配置
docker inspect container_name | grep -A 20 "NetworkSettings"

# 查看容器 IP 地址
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name

# 查看容器端口映射
docker port container_name

# 在容器内查看网络配置
docker exec container_name ip addr show
docker exec container_name netstat -tulpn

Bridge 网络

默认 Bridge 网络

bash
# 运行容器使用默认 bridge 网络
docker run -d --name web1 nginx
docker run -d --name web2 nginx

# 查看默认网络
docker network inspect bridge

# 容器间通信(通过 IP 地址)
docker exec web1 ping $(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web2)

自定义 Bridge 网络

bash
# 创建自定义 bridge 网络
docker network create --driver bridge mybridge

# 指定子网和网关
docker network create \
  --driver bridge \
  --subnet=172.20.0.0/16 \
  --ip-range=172.20.240.0/20 \
  --gateway=172.20.0.1 \
  mybridge

# 在自定义网络中运行容器
docker run -d --name web1 --network mybridge nginx
docker run -d --name web2 --network mybridge nginx

# 容器间通信(通过容器名)
docker exec web1 ping web2

Bridge 网络配置选项

bash
# 创建带配置的 bridge 网络
docker network create \
  --driver bridge \
  --subnet=192.168.100.0/24 \
  --gateway=192.168.100.1 \
  --ip-range=192.168.100.128/25 \
  --opt com.docker.network.bridge.name=mybr0 \
  --opt com.docker.network.bridge.enable_icc=true \
  --opt com.docker.network.bridge.enable_ip_masquerade=true \
  --opt com.docker.network.driver.mtu=1500 \
  advanced-bridge

# 指定容器 IP 地址
docker run -d --name web \
  --network advanced-bridge \
  --ip 192.168.100.10 \
  nginx

Host 网络

Host 网络使用

bash
# 使用主机网络
docker run -d --name web --network host nginx

# 查看容器网络(与主机相同)
docker exec web ip addr show

# 直接访问主机端口
curl http://localhost:80

Host 网络特点

优势:

  • 网络性能最佳,无 NAT 开销
  • 容器可以直接绑定主机端口
  • 适合高性能网络应用

劣势:

  • 容器与主机共享网络命名空间
  • 端口冲突风险
  • 安全性较低
bash
# 示例:高性能数据库
docker run -d \
  --name postgres \
  --network host \
  -e POSTGRES_PASSWORD=password \
  postgres:13

# 直接连接到主机的 5432 端口
psql -h localhost -U postgres

None 网络

禁用网络

bash
# 创建无网络容器
docker run -d --name isolated --network none alpine sleep 3600

# 查看网络配置(只有 loopback)
docker exec isolated ip addr show

# 手动配置网络(如果需要)
docker exec isolated ip link add eth0 type dummy

应用场景

bash
# 安全处理敏感数据
docker run --rm -it \
  --network none \
  --volume /host/data:/data:ro \
  my-secure-processor

# 离线数据处理
docker run --rm \
  --network none \
  --volume /input:/input:ro \
  --volume /output:/output \
  data-processor

自定义网络

创建多网络架构

bash
# 创建前端网络
docker network create frontend

# 创建后端网络
docker network create backend

# 创建数据库网络
docker network create database

# Web 服务器(连接前端和后端)
docker run -d --name web \
  --network frontend \
  nginx

docker network connect backend web

# API 服务器(连接后端和数据库)
docker run -d --name api \
  --network backend \
  myapi

docker network connect database api

# 数据库(只连接数据库网络)
docker run -d --name db \
  --network database \
  postgres

网络别名

bash
# 创建网络
docker network create mynetwork

# 使用网络别名
docker run -d --name web1 \
  --network mynetwork \
  --network-alias web \
  nginx

docker run -d --name web2 \
  --network mynetwork \
  --network-alias web \
  nginx

# 通过别名访问(负载均衡)
docker run --rm --network mynetwork alpine \
  nslookup web

端口映射

基本端口映射

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

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

# 映射到指定 IP
docker run -d -p 127.0.0.1:8080:80 --name web nginx

# 映射 UDP 端口
docker run -d -p 8080:80/udp --name app myapp

# 映射端口范围
docker run -d -p 8000-8010:8000-8010 --name app myapp

# 映射到随机端口
docker run -d -P --name web nginx

动态端口映射

bash
# 查看映射的随机端口
docker port web 80

# 获取端口号用于脚本
PORT=$(docker port web 80 | cut -d: -f2)
echo "Web server is running on port $PORT"

# 使用环境变量
docker run -d -p ${HOST_PORT:-8080}:80 --name web nginx

容器间通信

同网络容器通信

bash
# 创建应用网络
docker network create app-network

# 运行数据库
docker run -d --name database \
  --network app-network \
  -e POSTGRES_PASSWORD=password \
  postgres:13

# 运行应用(通过容器名连接数据库)
docker run -d --name webapp \
  --network app-network \
  -e DATABASE_URL=postgresql://postgres:password@database:5432/mydb \
  mywebapp

# 测试连接
docker exec webapp ping database

跨网络容器通信

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

# API 网关连接两个网络
docker run -d --name gateway \
  --network frontend \
  nginx

docker network connect backend gateway

# 前端服务
docker run -d --name frontend-app \
  --network frontend \
  my-frontend

# 后端服务
docker run -d --name backend-app \
  --network backend \
  my-backend

服务发现

DNS 服务发现

bash
# 创建网络
docker network create service-network

# 运行服务
docker run -d --name service1 \
  --network service-network \
  --hostname service1.local \
  myservice

docker run -d --name service2 \
  --network service-network \
  --hostname service2.local \
  myservice

# DNS 查询
docker run --rm --network service-network alpine \
  nslookup service1

docker run --rm --network service-network alpine \
  dig service1.local

使用 Consul 服务发现

yaml
# docker-compose.yml
version: '3.8'

services:
  consul:
    image: consul:latest
    ports:
      - "8500:8500"
    command: agent -server -bootstrap -ui -client=0.0.0.0
    networks:
      - service-network

  service1:
    image: myservice
    depends_on:
      - consul
    environment:
      - CONSUL_URL=http://consul:8500
      - SERVICE_NAME=service1
    networks:
      - service-network

  service2:
    image: myservice
    depends_on:
      - consul
    environment:
      - CONSUL_URL=http://consul:8500
      - SERVICE_NAME=service2
    networks:
      - service-network

networks:
  service-network:
    driver: bridge

负载均衡

Nginx 负载均衡

nginx
# nginx.conf
upstream backend {
    server backend1:8080;
    server backend2:8080;
    server backend3:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
yaml
# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - backend1
      - backend2
      - backend3
    networks:
      - app-network

  backend1:
    image: mybackend
    networks:
      - app-network

  backend2:
    image: mybackend
    networks:
      - app-network

  backend3:
    image: mybackend
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

HAProxy 负载均衡

# haproxy.cfg
global
    daemon

defaults
    mode http
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend web_frontend
    bind *:80
    default_backend web_servers

backend web_servers
    balance roundrobin
    server web1 web1:80 check
    server web2 web2:80 check
    server web3 web3:80 check

网络安全

网络隔离

bash
# 创建隔离的内部网络
docker network create --internal backend-network

# 只有后端服务可以访问数据库
docker run -d --name database \
  --network backend-network \
  postgres

docker run -d --name api \
  --network backend-network \
  myapi

# 前端无法直接访问数据库
docker run -d --name frontend \
  --network frontend-network \
  myfrontend

防火墙规则

bash
# 限制容器网络访问
iptables -I DOCKER-USER -s 172.17.0.0/16 -d 192.168.1.0/24 -j DROP

# 允许特定端口
iptables -I DOCKER-USER -p tcp --dport 80 -j ACCEPT
iptables -I DOCKER-USER -p tcp --dport 443 -j ACCEPT

# 限制容器间通信
iptables -I DOCKER-USER -i docker0 -o docker0 -j DROP

网络加密

yaml
# 使用 TLS 加密的服务
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "443:443"
    volumes:
      - ./ssl:/etc/nginx/ssl:ro
      - ./nginx-ssl.conf:/etc/nginx/nginx.conf:ro
    networks:
      - secure-network

  app:
    image: myapp
    environment:
      - TLS_CERT_FILE=/certs/cert.pem
      - TLS_KEY_FILE=/certs/key.pem
    volumes:
      - ./certs:/certs:ro
    networks:
      - secure-network

networks:
  secure-network:
    driver: bridge
    driver_opts:
      encrypted: "true"

网络监控

网络流量监控

bash
# 监控容器网络流量
docker exec container_name netstat -i

# 使用 iftop 监控
docker exec -it container_name iftop

# 监控网络连接
docker exec container_name ss -tulpn

# 网络性能测试
docker run --rm --network mynetwork alpine \
  sh -c "apk add --no-cache iperf3 && iperf3 -c target_container"

网络诊断工具

bash
# 网络连通性测试
docker run --rm --network mynetwork alpine ping target_container

# DNS 解析测试
docker run --rm --network mynetwork alpine nslookup target_container

# 端口连通性测试
docker run --rm --network mynetwork alpine \
  sh -c "apk add --no-cache netcat-openbsd && nc -zv target_container 80"

# 路由跟踪
docker run --rm --network mynetwork alpine traceroute target_container

高级网络配置

Macvlan 网络

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

# 运行容器获得独立 MAC 地址
docker run -d --name web \
  --network macvlan-network \
  --ip 192.168.1.100 \
  nginx

Overlay 网络(Swarm 模式)

bash
# 初始化 Swarm
docker swarm init

# 创建 overlay 网络
docker network create --driver overlay --attachable myoverlay

# 跨节点容器通信
docker run -d --name web1 --network myoverlay nginx
docker run -d --name web2 --network myoverlay nginx

# 在不同节点上的容器可以直接通信

自定义网络驱动

bash
# 安装第三方网络插件
docker plugin install store/weaveworks/net-plugin:latest

# 使用自定义驱动创建网络
docker network create --driver weave myweave

# 运行容器
docker run -d --network myweave nginx

故障排查

网络问题诊断

bash
# 检查网络配置
docker network ls
docker network inspect network_name

# 检查容器网络
docker inspect container_name | grep -A 20 "NetworkSettings"

# 测试网络连通性
docker exec container1 ping container2

# 检查端口监听
docker exec container_name netstat -tulpn

# 查看路由表
docker exec container_name ip route show

# 检查 iptables 规则
sudo iptables -L DOCKER-USER
sudo iptables -L DOCKER

常见问题解决

bash
# 问题 1: 容器无法访问外网
# 检查 DNS 配置
docker exec container_name cat /etc/resolv.conf

# 重启 Docker 服务
sudo systemctl restart docker

# 问题 2: 端口映射不生效
# 检查防火墙规则
sudo ufw status
sudo iptables -L

# 问题 3: 容器间无法通信
# 检查网络连接
docker network inspect network_name

# 重新连接网络
docker network disconnect network_name container_name
docker network connect network_name container_name

性能优化

网络性能调优

bash
# 调整网络缓冲区大小
echo 'net.core.rmem_max = 134217728' >> /etc/sysctl.conf
echo 'net.core.wmem_max = 134217728' >> /etc/sysctl.conf

# 优化 TCP 参数
echo 'net.ipv4.tcp_congestion_control = bbr' >> /etc/sysctl.conf

# 应用配置
sysctl -p

容器网络优化

bash
# 使用 host 网络提高性能
docker run -d --network host high-performance-app

# 调整 MTU 大小
docker network create --driver bridge \
  --opt com.docker.network.driver.mtu=9000 \
  jumbo-network

# 禁用不必要的网络功能
docker run -d \
  --sysctl net.ipv6.conf.all.disable_ipv6=1 \
  myapp

本章小结

本章全面介绍了 Docker 网络配置的各个方面:

关键要点:

  • 网络模式:bridge、host、none、overlay 等不同模式
  • 自定义网络:创建隔离的网络环境
  • 服务发现:容器间通过名称通信
  • 负载均衡:分发流量到多个容器
  • 网络安全:隔离和加密网络通信
  • 监控诊断:网络问题排查和性能优化

最佳实践:

  • 使用自定义网络而不是默认 bridge
  • 合理设计网络架构和隔离策略
  • 实施适当的安全措施
  • 监控网络性能和流量
  • 定期检查和优化网络配置

在下一章中,我们将学习 Docker 的故障排查,包括常见问题诊断和解决方案。

延伸阅读

本站内容仅供学习和研究使用。