Docker网络

一、Docker网络概述

1.1 网络架构

1.1.1 Docker网络原理

网络架构图

┌─────────────────────────────────────────┐
│           Docker主机网络                 │
├─────────────────────────────────────────┤
│                                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐
│  │ Container│  │ Container│  │ Container│
│  │   eth0   │  │   eth0   │  │   eth0   │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘
│       │             │             │
│  ┌────┴─────────────┴─────────────┴─────┐
│  │      docker0 (Bridge Network)        │
│  │      172.17.0.1/16                   │
│  └──────────────┬───────────────────────┘
│                 │
│  ┌──────────────┴───────────────────────┐
│  │         eth0 (Host Network)          │
│  │         192.168.1.100                │
│  └──────────────┬───────────────────────┘
└─────────────────┼─────────────────────────┘
                  │
         ┌────────┴────────┐
         │   外部网络       │
         └─────────────────┘

东巴文理解

Docker网络 = 虚拟交换机
就像:为每个容器分配独立的网络接口

网络组成:
├─ docker0网桥:虚拟交换机
├─ veth pair:虚拟网线
├─ 容器网卡:eth0
└─ iptables:网络地址转换

工作原理:
├─ 容器通过veth pair连接到docker0
├─ docker0作为网桥转发数据包
├─ iptables实现NAT和端口映射
└─ 容器可以相互通信和访问外部网络

1.1.2 网络命名空间

命名空间概念

网络命名空间:
├─ 隔离网络资源
├─ 独立的网络栈
├─ 独立的IP地址
├─ 独立的路由表
└─ 独立的iptables规则

每个容器:
├─ 有自己的网络命名空间
├─ 有自己的网络设备
├─ 有自己的IP地址
└─ 与其他容器网络隔离

1.2 网络模式

1.2.1 五种网络模式

模式列表

bridge模式(默认):
├─ 桥接网络
├─ 容器连接到docker0网桥
├─ 容器有独立IP
└─ 通过NAT访问外部

host模式:
├─ 主机网络
├─ 容器共享主机网络
├─ 没有网络隔离
└─ 性能最优

none模式:
├─ 无网络
├─ 容器没有网络接口
├─ 完全网络隔离
└─ 安全性最高

container模式:
├─ 容器网络
├─ 共享另一个容器的网络
├─ 共享IP和端口
└─ 用于容器间通信

自定义网络:
├─ 用户创建的网络
├─ 支持DNS解析
├─ 灵活配置
└─ 推荐使用

二、Bridge网络模式

2.1 Bridge模式原理

2.1.1 工作原理

网络拓扑

┌───────────────────────────────────────┐
│           Docker主机                   │
├───────────────────────────────────────┤
│                                       │
│  ┌──────────┐        ┌──────────┐    │
│  │ Container│        │ Container│    │
│  │ 172.17.0.2│       │ 172.17.0.3│   │
│  └────┬─────┘        └────┬─────┘    │
│       │ veth              │ veth     │
│       └─────┬─────────────┘          │
│             │                        │
│      ┌──────┴──────┐                 │
│      │   docker0   │                 │
│      │ 172.17.0.1  │                 │
│      └──────┬──────┘                 │
│             │                        │
│      ┌──────┴──────┐                 │
│      │    eth0     │                 │
│      │ 192.168.1.100│                │
│      └──────┬──────┘                 │
└─────────────┼─────────────────────────┘
              │
       外部网络

数据包转发

容器访问外部:
├─ 容器(172.17.0.2) → docker0(172.17.0.1)
├─ docker0 → eth0(192.168.1.100)
├─ iptables NAT转换
└─ 发送到外部网络

外部访问容器:
├─ 外部请求 → eth0:8080
├─ iptables端口映射
├─ 转发到容器(172.17.0.2:80)
└─ 容器处理请求

2.1.2 默认bridge网络

查看默认网络

# 查看网络列表
docker network ls

# 输出
NETWORK ID     NAME      DRIVER    SCOPE
a1b2c3d4e5f6   bridge    bridge    local
b2c3d4e5f6a7   host      host      local
c3d4e5f6a7b8   none      null      local

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

# 输出
[
    {
        "Name": "bridge",
        "Id": "a1b2c3d4e5f6...",
        "Driver": "bridge",
        "IPAM": {
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Containers": {
            "容器ID": {
                "Name": "mynginx",
                "IPv4Address": "172.17.0.2/16"
            }
        }
    }
]

2.2 使用Bridge模式

2.2.1 创建容器

基本使用

# 默认使用bridge模式
docker run -d --name mynginx nginx:latest

# 指定bridge模式
docker run -d --name mynginx --net=bridge nginx:latest

# 查看容器网络
docker inspect mynginx | grep IPAddress

# 输出
"IPAddress": "172.17.0.2"

端口映射

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

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

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

# 随机端口映射
docker run -d -P --name mynginx nginx:latest

# 查看端口映射
docker port mynginx

# 输出
80/tcp -> 0.0.0.0:8080

2.2.2 容器间通信

默认bridge网络限制

# 创建两个容器
docker run -d --name web nginx:latest
docker run -d --name app myapp:latest

# 进入web容器
docker exec -it web bash

# 尝试通过容器名访问app容器
ping app
# ping: app: Name or service not known

# 只能通过IP访问
ping 172.17.0.3
# PING 172.17.0.3 (172.17.0.3): 56 data bytes

说明

默认bridge网络:
❌ 不支持DNS解析
❌ 容器间不能通过名称访问
❌ 只能通过IP地址访问
❌ 需要使用--link(已废弃)

解决方案:
✅ 使用自定义网络
✅ 支持DNS解析
✅ 容器间可通过名称访问

三、Host网络模式

3.1 Host模式原理

3.1.1 工作原理

网络拓扑

┌───────────────────────────────────────┐
│           Docker主机                   │
├───────────────────────────────────────┤
│                                       │
│  ┌──────────┐                        │
│  │ Container│                        │
│  │ 共享网络命名空间                    │
│  └────┬─────┘                        │
│       │                              │
│  ┌────┴─────────────────────────────┐
│  │         eth0                     │
│  │      192.168.1.100               │
│  │   共享主机网络栈                   │
│  └──────────────┬───────────────────┘
└─────────────────┼─────────────────────┘
                  │
         外部网络

特点

Host模式:
├─ 容器共享主机网络命名空间
├─ 使用主机IP地址
├─ 使用主机端口
├─ 没有网络隔离
├─ 性能最优
└─ 端口冲突风险

优势:
✅ 网络性能最优(无NAT)
✅ 无需端口映射
✅ 适合高性能应用

劣势:
❌ 没有网络隔离
❌ 端口冲突风险
❌ 安全性较低

3.2 使用Host模式

3.2.1 创建容器

基本使用

# 使用host模式
docker run -d --name mynginx --net=host nginx:latest

# 查看容器网络
docker inspect mynginx | grep NetworkMode

# 输出
"NetworkMode": "host"

# 容器直接使用主机端口
curl http://localhost:80

注意事项

# 端口冲突示例
docker run -d --name nginx1 --net=host nginx:latest
docker run -d --name nginx2 --net=host nginx:latest

# nginx2启动失败
# Error: port is already allocated

# 解决方法:修改应用端口
docker run -d --name nginx2 --net=host -e NGINX_PORT=8080 nginx:latest

3.2.2 适用场景

推荐场景

高性能应用:
├─ 网络密集型应用
├─ 需要极低网络延迟
├─ 大量网络IO
└─ 示例:游戏服务器、实时通信

端口已知应用:
├─ 应用端口固定
├─ 不需要动态端口映射
└─ 示例:数据库、消息队列

网络监控:
├─ 需要监控主机网络
├─ 需要访问主机网络接口
└─ 示例:网络监控工具

四、None网络模式

4.1 None模式原理

4.1.1 工作原理

网络拓扑

┌───────────────────────────────────────┐
│           Docker主机                   │
├───────────────────────────────────────┤
│                                       │
│  ┌──────────┐                        │
│  │ Container│                        │
│  │  lo (127.0.0.1)                   │
│  │  没有其他网络接口                   │
│  └──────────┘                        │
│                                       │
│  ┌────────────────────────────────────┐
│  │         eth0                       │
│  │      192.168.1.100                 │
│  └──────────────┬─────────────────────┘
└─────────────────┼─────────────────────┘
                  │
         外部网络

特点

None模式:
├─ 容器没有网络接口
├─ 只有loopback接口
├─ 完全网络隔离
├─ 安全性最高
└─ 需要手动配置网络

优势:
✅ 完全网络隔离
✅ 安全性最高
✅ 适合敏感应用

劣势:
❌ 无法访问外部网络
❌ 外部无法访问容器
❌ 需要手动配置网络

4.2 使用None模式

4.2.1 创建容器

基本使用

# 使用none模式
docker run -d --name myapp --net=none myapp:latest

# 查看容器网络
docker exec myapp ip addr

# 输出
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo

# 只有loopback接口,没有其他网络接口

4.2.2 适用场景

推荐场景

安全敏感应用:
├─ 不需要网络访问
├─ 完全隔离环境
└─ 示例:加密解密服务

离线处理:
├─ 本地数据处理
├─ 不需要网络连接
└─ 示例:批处理任务

测试环境:
├─ 测试网络隔离
├─ 安全测试
└─ 示例:渗透测试

五、Container网络模式

5.1 Container模式原理

5.1.1 工作原理

网络拓扑

┌───────────────────────────────────────┐
│           Docker主机                   │
├───────────────────────────────────────┤
│                                       │
│  ┌──────────┐        ┌──────────┐    │
│  │ Container│        │ Container│    │
│  │  (Web)   │        │  (App)   │    │
│  └────┬─────┘        └────┬─────┘    │
│       │                   │          │
│       └─────┬─────────────┘          │
│             │ 共享网络命名空间         │
│      ┌──────┴──────┐                 │
│      │   docker0   │                 │
│      │ 172.17.0.2  │                 │
│      └──────┬──────┘                 │
└─────────────┼─────────────────────────┘
              │
       外部网络

特点

Container模式:
├─ 共享另一个容器的网络命名空间
├─ 共享IP地址和端口
├─ 共享网络配置
├─ 可以通过localhost通信
└─ 紧密耦合的容器

优势:
✅ 容器间通信高效
✅ 共享网络资源
✅ 适合紧密耦合的应用

劣势:
❌ 网络隔离性差
❌ 端口冲突风险
❌ 依赖关系复杂

5.2 使用Container模式

5.2.1 创建容器

基本使用

# 创建第一个容器
docker run -d --name web nginx:latest

# 创建第二个容器,共享web容器的网络
docker run -d --name app --net=container:web myapp:latest

# 查看两个容器的IP
docker inspect web | grep IPAddress
docker inspect app | grep IPAddress

# 输出(IP地址相同)
"IPAddress": "172.17.0.2"
"IPAddress": "172.17.0.2"

# 在app容器中访问web容器
docker exec app curl http://localhost:80

5.2.2 适用场景

推荐场景

紧密耦合应用:
├─ Web服务器 + 应用服务器
├─ 需要通过localhost通信
└─ 示例:Nginx + PHP-FPM

监控代理:
├─ 应用容器 + 监控代理
├─ 共享网络命名空间
└─ 示例:应用 + Sidecar

调试工具:
├─ 应用容器 + 调试工具
├─ 共享网络环境
└─ 示例:应用 + 网络调试工具

六、自定义网络

6.1 创建自定义网络

6.1.1 docker network命令

基本语法

docker network create [OPTIONS] NETWORK

OPTIONS:
      --attachable           允许手动连接容器
      --aux-address map      辅助IP地址
      --config-from string   从指定网络复制配置
      --config-only          创建仅配置网络
  -d, --driver string        网络驱动(bridge/overlay)
      --gateway strings      网关
      --internal             禁止外部访问
      --ip-range strings     IP地址范围
      --ipam-driver string   IPAM驱动
      --ipam-opt map         IPAM选项
      --ipv6                 启用IPv6
      --label list           设置标签
  -o, --opt map              网络选项
      --scope string         网络范围
      --subnet strings       子网

使用示例

# 创建bridge网络
docker network create mynetwork

# 指定子网和网关
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  mynetwork

# 指定IP范围
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --ip-range 172.20.1.0/24 \
  mynetwork

# 创建overlay网络(用于Swarm)
docker network create -d overlay myoverlay

# 查看网络
docker network ls

# 查看网络详情
docker network inspect mynetwork

6.1.2 网络驱动类型

驱动类型

bridge(默认):
├─ 单主机网络
├─ 容器间通信
└─ 适合单机部署

overlay:
├─ 多主机网络
├─ 跨主机容器通信
├─ 用于Docker Swarm
└─ 适合集群部署

macvlan:
├─ 容器有独立MAC地址
├─ 直接连接到物理网络
├─ 性能最优
└─ 需要网络设备支持

ipvlan:
├─ 类似macvlan
├─ 共享MAC地址
└─ 需要网络设备支持

none:
├─ 无网络
└─ 完全隔离

host:
├─ 主机网络
└─ 共享主机网络栈

6.2 使用自定义网络

6.2.1 连接容器到网络

基本使用

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

# 创建容器并连接到网络
docker run -d --name web --net mynetwork nginx:latest
docker run -d --name app --net mynetwork myapp:latest

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

# 进入web容器,通过容器名访问app容器
docker exec -it web bash
ping app
# PING app (172.20.0.3): 56 data bytes

# DNS解析成功!

优势

自定义网络:
✅ 支持DNS解析
✅ 容器间可通过名称访问
✅ 动态连接和断开
✅ 网络隔离
✅ 灵活配置

6.2.2 管理网络连接

docker network connect

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

# 指定IP地址
docker network connect --ip 172.20.0.100 mynetwork mycontainer

# 指定别名
docker network connect --alias web mynetwork mycontainer

# 查看容器连接的网络
docker inspect mycontainer | grep Networks

docker network disconnect

# 断开容器与网络的连接
docker network disconnect mynetwork mycontainer

# 强制断开
docker network disconnect -f mynetwork mycontainer

6.3 网络配置选项

6.3.1 网络选项

常用选项

# 创建网络时设置MTU
docker network create -d bridge -o com.docker.network.driver.mtu=1400 mynetwork

# 设置网络内部(禁止外部访问)
docker network create --internal mynetwork

# 设置IPv6网络
docker network create --ipv6 --subnet fd00:dead:beef::/48 mynetwork

# 设置DNS服务器
docker run -d --name mycontainer --dns 8.8.8.8 --net mynetwork nginx

# 设置DNS搜索域
docker run -d --name mycontainer --dns-search example.com --net mynetwork nginx

# 设置主机名
docker run -d --name mycontainer --hostname myhost --net mynetwork nginx

6.3.2 容器网络配置

IP地址配置

# 指定容器IP地址
docker run -d --name web --net mynetwork --ip 172.20.0.100 nginx:latest

# 指定MAC地址
docker run -d --name web --net mynetwork --mac-address 02:42:ac:14:00:64 nginx:latest

# 指定多个网络
docker run -d --name web --net network1 --net network2 nginx:latest

七、网络故障排查

7.1 常用排查命令

7.1.1 查看网络信息

查看网络列表

# 查看所有网络
docker network ls

# 输出
NETWORK ID     NAME        DRIVER    SCOPE
a1b2c3d4e5f6   bridge      bridge    local
b2c3d4e5f6a7   host        host      local
c3d4e5f6a7b8   none        null      local
d4e5f6a7b8c9   mynetwork   bridge    local

查看网络详情

# 查看网络配置
docker network inspect mynetwork

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

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

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

7.1.2 测试网络连接

进入容器测试

# 进入容器
docker exec -it mycontainer bash

# 测试网络连接
ping 8.8.8.8
ping google.com

# 查看网络接口
ip addr

# 查看路由表
ip route

# 查看DNS解析
cat /etc/resolv.conf
nslookup google.com

# 测试端口连接
curl http://localhost:80
telnet localhost 80

从主机测试

# 测试容器端口
curl http://localhost:8080

# 查看端口监听
netstat -tulpn | grep 8080

# 查看iptables规则
iptables -t nat -L -n

# 查看网络连接
ss -tulpn

7.2 常见问题与解决

7.2.1 容器无法访问外部网络

问题排查

# 1. 检查容器网络模式
docker inspect mycontainer | grep NetworkMode

# 2. 检查容器DNS
docker exec mycontainer cat /etc/resolv.conf

# 3. 检查主机网络
ping 8.8.8.8

# 4. 检查iptables规则
iptables -t nat -L -n

# 5. 检查IP转发
cat /proc/sys/net/ipv4/ip_forward
# 应该为1

解决方法

# 启用IP转发
echo 1 > /proc/sys/net/ipv4/ip_forward

# 或修改配置文件
vim /etc/sysctl.conf
net.ipv4.ip_forward=1

# 应用配置
sysctl -p

# 重启Docker
systemctl restart docker

7.2.2 容器间无法通信

问题排查

# 1. 检查容器是否在同一网络
docker network inspect mynetwork

# 2. 检查防火墙规则
iptables -L -n

# 3. 检查容器IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container1
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container2

# 4. 测试连通性
docker exec container1 ping container2

解决方法

# 使用自定义网络
docker network create mynetwork
docker network connect mynetwork container1
docker network connect mynetwork container2

# 或重新创建容器
docker run -d --name container1 --net mynetwork image1
docker run -d --name container2 --net mynetwork image2

7.2.3 端口映射不生效

问题排查

# 1. 检查端口映射
docker port mycontainer

# 2. 检查容器进程
docker exec mycontainer netstat -tulpn

# 3. 检查主机端口
netstat -tulpn | grep 8080

# 4. 检查iptables规则
iptables -t nat -L -n | grep 8080

解决方法

# 检查容器内应用是否监听正确端口
docker exec mycontainer netstat -tulpn

# 检查应用配置
docker exec mycontainer cat /etc/nginx/nginx.conf

# 重新创建容器,确保端口映射正确
docker run -d -p 8080:80 --name mycontainer nginx:latest

八、本章小结

8.1 网络模式总结

8.1.1 五种网络模式对比

Bridge模式:
├─ 默认模式
├─ 容器有独立IP
├─ 通过NAT访问外部
├─ 需要端口映射
└─ 推荐使用自定义bridge

Host模式:
├─ 共享主机网络
├─ 性能最优
├─ 无网络隔离
├─ 端口冲突风险
└─ 适合高性能应用

None模式:
├─ 完全网络隔离
├─ 安全性最高
├─ 无法访问外部
└─ 适合安全敏感应用

Container模式:
├─ 共享容器网络
├─ 共享IP和端口
├─ 通过localhost通信
└─ 适合紧密耦合应用

自定义网络:
├─ 支持DNS解析
├─ 灵活配置
├─ 网络隔离
└─ 推荐使用

8.1.2 网络命令总结

网络管理:
├─ docker network ls:查看网络列表
├─ docker network create:创建网络
├─ docker network rm:删除网络
├─ docker network inspect:查看网络详情
├─ docker network connect:连接容器到网络
└─ docker network disconnect:断开容器与网络

网络排查:
├─ docker port:查看端口映射
├─ docker inspect:查看容器网络配置
├─ docker exec:进入容器测试网络
└─ iptables:查看防火墙规则

8.2 最佳实践

8.2.1 网络设计建议

网络规划:
✅ 使用自定义网络
✅ 按应用类型划分网络
✅ 合理规划IP地址段
✅ 设置网络隔离

容器部署:
✅ 使用自定义网络
✅ 通过容器名访问
✅ 避免使用默认bridge
✅ 合理配置端口映射

安全建议:
✅ 使用网络隔离
✅ 限制容器间通信
✅ 配置防火墙规则
✅ 定期检查网络配置

8.2.2 性能优化

网络性能:
✅ 高性能应用使用host模式
✅ 合理设置MTU
✅ 优化DNS配置
✅ 使用连接池

网络监控:
✅ 监控网络流量
✅ 监控网络延迟
✅ 监控网络错误
✅ 设置告警

8.3 下一章预告

下一章:Docker存储

将学习:

  • 💾 Docker存储驱动
  • 📦 数据卷管理
  • 🗂️ 挂载点配置
  • 🔧 存储性能优化

📝 练习题

基础题

  1. 网络模式:创建三个容器,分别使用bridge、host、none网络模式,观察它们的网络配置差异。

  2. 端口映射:创建一个nginx容器,映射端口8080:80,然后在浏览器中访问。

  3. 自定义网络:创建一个自定义bridge网络,将两个容器连接到该网络,测试容器间通过名称通信。

进阶题

  1. 网络隔离:创建两个自定义网络network1和network2,创建三个容器,其中两个连接到network1,一个连接到network2,测试网络隔离效果。

  2. Container模式:创建一个nginx容器和一个调试容器,调试容器共享nginx容器的网络,测试通过localhost访问nginx。

  3. 故障排查:模拟一个容器无法访问外部网络的场景,排查并解决问题。

实践题

  1. 完整应用网络:为一个三层Web应用(前端、后端、数据库)设计网络架构,要求:

    • 前端可被外部访问
    • 后端只能被前端访问
    • 数据库只能被后端访问
    • 使用自定义网络实现隔离
  2. 网络监控:部署一个网络监控容器,监控其他容器的网络流量和连接状态。


🔗 扩展阅读

官方文档

深入理解