第07章:Docker 网络模型

第07章:Docker 网络模型

本章目标:理解 Docker 的四种网络模式,掌握容器间通信、DNS 解析和自定义网络的配置方法。


7.1 Docker 网络架构概览

7.1.1 网络层次

复制代码
┌────────────────────────────────────────────────────────┐
│                    Docker 网络层次                      │
│                                                        │
│  ┌──────────────────────────────────────────────────┐ │
│  │              应用层(容器内)                      │ │
│  │  App A (port 80)  App B (port 8080)  App C (...) │ │
│  └──────────────────────┬───────────────────────────┘ │
│                         │                              │
│  ┌──────────────────────┴───────────────────────────┐ │
│  │           网络抽象层(libnetwork)                 │ │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐         │ │
│  │  │  bridge  │ │  host    │ │  none    │  ...     │ │
│  │  └──────────┘ └──────────┘ └──────────┘         │ │
│  └──────────────────────┬───────────────────────────┘ │
│                         │                              │
│  ┌──────────────────────┴───────────────────────────┐ │
│  │            系统层(Linux Kernel)                  │ │
│  │  Network Namespaces / veth pairs / iptables      │ │
│  └──────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘

7.1.2 查看网络

bash 复制代码
# 列出所有 Docker 网络
docker network ls
# NETWORK ID     NAME      DRIVER    SCOPE
# abc123def456   bridge    bridge    local
# def456abc123   host      host      local
# ghi789jkl012   none      null      local

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

# 查看容器的网络配置
docker inspect --format='{{json .NetworkSettings.Networks}}' <container>

7.2 四种网络模式详解

7.2.1 bridge(桥接网络)------ 默认模式

复制代码
bridge 网络原理:

┌─────────────────────────────────────────────────────┐
│                    宿主机                            │
│                                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────┐│
│  │  容器 A       │  │  容器 B       │  │  容器 C   ││
│  │ eth0         │  │ eth0         │  │ eth0      ││
│  │ 172.17.0.2   │  │ 172.17.0.3   │  │ 172.17.0.4││
│  └──────┬───────┘  └──────┬───────┘  └─────┬─────┘│
│         │                 │                 │       │
│    ┌────┴─────────────────┴─────────────────┴────┐ │
│    │              docker0 网桥                     │ │
│    │              172.17.0.1                       │ │
│    └──────────────────────┬───────────────────────┘ │
│                           │                          │
│    ┌──────────────────────┴───────────────────────┐ │
│    │              eth0 (宿主机网卡)                 │ │
│    │              192.168.1.100                    │ │
│    └──────────────────────┬───────────────────────┘ │
│                           │                          │
└───────────────────────────┼──────────────────────────┘
                            │
                       ┌────┴────┐
                       │  路由器  │
                       └────┬────┘
                            │
                       ┌────┴────┐
                       │  互联网  │
                       └─────────┘
bash 复制代码
# 使用默认 bridge 网络
docker run -d --name web1 nginx
docker run -d --name web2 nginx

# 查看容器 IP
docker inspect --format='{{.NetworkSettings.IPAddress}}' web1
# 172.17.0.2

docker inspect --format='{{.NetworkSettings.IPAddress}}' web2
# 172.17.0.3

# 默认 bridge 网络的限制:
# 1. 容器间不能通过名称互相访问(只能用 IP)
# 2. 需要手动配置端口映射
# 3. 所有容器共享同一个 bridge 网络

7.2.2 host(主机网络)

复制代码
host 网络原理:

┌──────────────────────────────────────────────┐
│                 宿主机                         │
│                                              │
│  ┌──────────────┐  ┌──────────────┐          │
│  │  容器 A       │  │  容器 B       │          │
│  │ (使用宿主机   │  │ (使用宿主机   │          │
│  │  网络栈)      │  │  网络栈)      │          │
│  └──────┬───────┘  └──────┬───────┘          │
│         │                 │                   │
│         └────────┬────────┘                   │
│                  │                            │
│  ┌───────────────┴──────────────────────────┐│
│  │           eth0 (宿主机网卡)                ││
│  │           192.168.1.100                   ││
│  └───────────────┬──────────────────────────┘│
│                  │                             │
└──────────────────┼─────────────────────────────┘
                   │
              ┌────┴────┐
              │  路由器  │
              └─────────┘
bash 复制代码
# 使用 host 网络
docker run -d --network host --name web nginx

# 容器直接使用宿主机的网络
# Nginx 监听宿主机的 80 端口
# 访问宿主机 IP:80 即可访问

# 查看容器网络
docker inspect --format='{{.NetworkSettings.Networks}}' web
# map[host:0xc000123456]

# host 网络的特点:
# ✅ 性能最好(没有 NAT 转换)
# ✅ 网络配置简单
# ❌ 端口冲突风险(多个容器不能监听同一端口)
# ❌ 网络隔离性差

7.2.3 none(无网络)

bash 复制代码
# 使用 none 网络(完全隔离)
docker run -d --network none --name isolated nginx

# 容器只有 loopback 接口
docker exec isolated ip addr
# 1: lo: <LOOPBACK,UP,LOWER_UP> ...
#     inet 127.0.0.1/8 scope host lo

# none 网络的适用场景:
# 1. 安全敏感的应用(完全网络隔离)
# 2. 不需要网络的批处理任务
# 3. 自定义网络配置

7.2.4 overlay(覆盖网络)

复制代码
overlay 网络原理(跨主机通信):

┌────────────────────────────┐  ┌────────────────────────────┐
│         主机 A              │  │         主机 B              │
│                            │  │                            │
│  ┌──────────┐ ┌──────────┐│  │ ┌──────────┐ ┌──────────┐│
│  │ 容器 A   │ │ 容器 B   ││  │ │ 容器 C   │ │ 容器 D   ││
│  │(overlay) │ │(overlay) ││  │ │(overlay) │ │(overlay) ││
│  └────┬─────┘ └────┬─────┘│  │ └────┬─────┘ └────┬─────┘│
│       │             │      │  │      │             │      │
│  ┌────┴─────────────┴────┐ │  │ ┌────┴─────────────┴────┐ │
│  │    overlay network    │◄├──┤►│    overlay network    │ │
│  │    10.0.0.0/24        │ │  │ │    10.0.0.0/24        │ │
│  └───────────┬───────────┘ │  │ └───────────┬───────────┘ │
│              │              │  │              │              │
│  ┌───────────┴───────────┐ │  │ ┌───────────┴───────────┐ │
│  │     docker_gwbridge    │ │  │ │     docker_gwbridge    │ │
│  │     172.18.0.0/16      │ │  │ │     172.18.0.0/16      │ │
│  └───────────┬───────────┘ │  │ └───────────┬───────────┘ │
│              │              │  │              │              │
│  ┌───────────┴───────────┐ │  │ ┌───────────┴───────────┐ │
│  │       eth0            │◄├──┤►│       eth0            │ │
│  │    192.168.1.101      │ │  │ │    192.168.1.102      │ │
│  └───────────────────────┘ │  │ └───────────────────────┘ │
└────────────────────────────┘  └────────────────────────────┘
bash 复制代码
# 创建 swarm 集群(overlay 需要 swarm 模式)
docker swarm init

# 创建 overlay 网络
docker network create -d overlay my-overlay

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

# overlay 网络的特点:
# ✅ 支持跨主机容器通信
# ✅ 自动 DNS 解析
# ✅ 支持服务发现
# ❌ 需要 Docker Swarm 或外部存储(如 Consul)

7.2.5 macvlan(MAC 地址虚拟化)

bash 复制代码
# macvlan 让容器拥有独立的 MAC 地址
# 容器在网络中就像独立的物理设备

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

# 使用 macvlan 网络
docker run -d --network my-macvlan --ip 192.168.1.100 --name web nginx

# macvlan 的特点:
# ✅ 容器有独立的 IP 和 MAC 地址
# ✅ 性能好(无 NAT)
# ❌ 需要物理网络支持
# ❌ 配置复杂

7.3 自定义网络

7.3.1 创建自定义网络

bash 复制代码
# 创建 bridge 类型的自定义网络
docker network create my-network

# 创建并配置参数
docker network create \
  --driver bridge \
  --subnet 192.168.100.0/24 \
  --gateway 192.168.100.1 \
  --ip-range 192.168.100.0/25 \
  --opt "com.docker.network.bridge.name"="my-bridge" \
  my-network

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

7.3.2 自定义网络的优势

bash 复制代码
# 1. 自动 DNS 解析(关键优势!)
docker network create my-net

docker run -d --name web-server --network my-net nginx
docker run -d --name app-server --network my-net myapp

# app-server 容器内可以直接通过 "web-server" 名称访问
# curl http://web-server:80  ✅ 自动解析!

# 2. 更好的隔离性
docker network create net-a
docker network create net-b

docker run -d --name web --network net-a nginx
docker run -d --name app --network net-b myapp

# web 和 app 互相隔离,不能通信

# 3. 灵活的网络配置
docker network create \
  --subnet 10.10.0.0/16 \
  --ipv6 \
  my-network-v6

7.3.3 将容器连接到多个网络

bash 复制代码
# 一个容器可以连接到多个网络
docker network create front-net
docker network create back-net

docker run -d --name web --network front-net nginx
docker run -d --name app --network back-net myapp

# 动态添加网络连接
docker network connect back-net web

# 现在 web 同时连接 front-net 和 back-net
# web 可以与两个网络中的容器通信

# 动态断开网络连接
docker network disconnect back-net web

7.4 容器 DNS 解析

7.4.1 自定义网络中的 DNS

bash 复制代码
# 创建自定义网络
docker network create app-net

# 启动多个容器
docker run -d --name db --network app-net mysql:8.0
docker run -d --name redis --network app-net redis:7
docker run -d --name web --network app-net myapp

# 在 web 容器中可以直接使用容器名访问
docker exec web ping db       # ✅ 解析到 db 容器的 IP
docker exec web ping redis    # ✅ 解析到 redis 容器的 IP

# 还可以使用网络别名
docker run -d --name db-primary --network app-net \
  --network-alias primary-db \
  mysql:8.0

# 使用别名访问
docker exec web ping primary-db  # ✅ 解析到 db-primary 容器

7.4.2 DNS 配置

bash 复制代码
# 自定义 DNS 服务器
docker run -d --dns 8.8.8.8 --dns 8.8.4.4 nginx

# 自定义 DNS 搜索域
docker run -d --dns-search example.com nginx

# 自定义 hosts 文件
docker run -d --add-host myhost:192.168.1.100 nginx

# 查看容器的 DNS 配置
docker exec <container> cat /etc/resolv.conf

7.5 端口映射详解

7.5.1 端口映射语法

bash 复制代码
# 基本语法
docker run -d -p <host_port>:<container_port> nginx

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

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

# 指定绑定地址
docker run -d -p 127.0.0.1:8080:80 nginx       # 仅本机访问
docker run -d -p 0.0.0.0:8080:80 nginx          # 所有地址(默认)
docker run -d -p 192.168.1.100:8080:80 nginx    # 指定网卡

# 随机端口
docker run -d -P nginx                          # 映射 EXPOSE 的所有端口
docker run -d -p 80 nginx                       # 主机随机端口 → 容器 80

# 查看端口映射
docker port <container>
# 80/tcp -> 0.0.0.0:8080

7.5.2 端口映射的实现原理

复制代码
端口映射底层原理(iptables):

宿主机                                    容器
┌─────────────────────┐            ┌─────────────────┐
│                     │            │                 │
│  访问 localhost:8080 │            │   nginx:80      │
│         │           │            │     ▲           │
│         ▼           │            │     │           │
│  iptables DNAT      │            │  docker0 网桥   │
│  8080 → 172.17.0.2:80│  ──────► │  172.17.0.2     │
│                     │            │                 │
└─────────────────────┘            └─────────────────┘

DNAT (Destination Network Address Translation)
目标网络地址转换:将访问宿主机 8080 端口的流量转发到容器的 80 端口
bash 复制代码
# 查看 iptables 规则(了解底层原理)
sudo iptables -t nat -L -n | grep 8080
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80

7.6 容器间通信实战

7.6.1 同一网络中的容器通信

bash 复制代码
# 创建应用网络
docker network create app-net

# 启动 MySQL 数据库
docker run -d \
  --name mysql-db \
  --network app-net \
  -e MYSQL_ROOT_PASSWORD=secret123 \
  -e MYSQL_DATABASE=myapp \
  mysql:8.0

# 启动 Redis 缓存
docker run -d \
  --name redis-cache \
  --network app-net \
  redis:7

# 启动应用
docker run -d \
  --name web-app \
  --network app-net \
  -p 8080:8080 \
  -e DB_HOST=mysql-db \
  -e DB_PORT=3306 \
  -e REDIS_HOST=redis-cache \
  -e REDIS_PORT=6379 \
  myapp:latest

# 在 web-app 容器内测试连接
docker exec web-app ping mysql-db      # ✅
docker exec web-app ping redis-cache   # ✅

7.6.2 跨网络通信

bash 复制代码
# 创建前后端网络
docker network create frontend
docker network create backend

# 启动 Nginx(前端)
docker run -d \
  --name nginx \
  --network frontend \
  -p 80:80 \
  nginx

# 启动应用(前后端都连接)
docker run -d \
  --name api-server \
  --network backend \
  myapi:latest

# 将 nginx 连接到 backend 网络
docker network connect backend nginx

# 现在 nginx 可以通过 api-server:8080 访问后端
# 但外部网络只能访问 nginx,无法直接访问 api-server

7.7 网络故障排查

7.7.1 常用排查命令

bash 复制代码
# 1. 查看容器网络配置
docker inspect --format='{{json .NetworkSettings}}' <container>

# 2. 进入容器检查网络
docker exec -it <container> ip addr
docker exec -it <container> ip route
docker exec -it <container> cat /etc/resolv.conf

# 3. 测试网络连通性
docker exec -it <container> ping <target>
docker exec -it <container> curl -v http://<target>:<port>

# 4. 查看 Docker 网络
docker network ls
docker network inspect <network>

# 5. 查看 iptables 规则
sudo iptables -t nat -L -n
sudo iptables -L -n

7.7.2 常见网络问题

问题 可能原因 解决方案
容器间无法通信 不在同一网络 连接到同一网络
无法通过名称访问 使用了默认 bridge 使用自定义网络
端口映射不生效 防火墙/iptables 检查防火墙规则
DNS 解析失败 DNS 配置错误 检查 /etc/resolv.conf
容器无法上网 网络配置问题 检查网桥和路由

7.8 动手实验

实验 7.1:网络模式对比

bash 复制代码
# 1. bridge 模式(默认)
docker run -d --name bridge-test nginx
docker inspect --format='{{.NetworkSettings.Networks}}' bridge-test
# map[bridge:...]

# 2. host 模式
docker run -d --name host-test --network host nginx
docker inspect --format='{{.NetworkSettings.Networks}}' host-test
# map[host:...]

# 3. none 模式
docker run -d --name none-test --network none nginx
docker exec none-test ip addr
# 只有 lo 接口

# 清理
docker rm -f bridge-test host-test none-test

实验 7.2:自定义网络 DNS 解析

bash 复制代码
# 1. 创建自定义网络
docker network create demo-net

# 2. 启动服务器容器
docker run -d --name server1 --network demo-net nginx
docker run -d --name server2 --network demo-net nginx

# 3. 在 server1 中测试 DNS 解析
docker exec server1 ping server2
# PING server2 (172.18.0.3): 56 data bytes
# 64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.089 ms

# 4. 使用网络别名
docker run -d --name server3 --network demo-net --network-alias myserver nginx
docker exec server1 ping myserver
# ✅ 解析到 server3

# 清理
docker rm -f server1 server2 server3
docker network rm demo-net

实验 7.3:端口映射

bash 复制代码
# 1. 多端口映射
docker run -d --name multi-port \
  -p 8080:80 \
  -p 8443:443 \
  -p 8081:8080 \
  nginx

# 2. 查看端口映射
docker port multi-port
# 80/tcp -> 0.0.0.0:8080
# 443/tcp -> 0.0.0.0:8443
# 8080/tcp -> 0.0.0.0:8081

# 3. 测试访问
curl http://localhost:8080
curl https://localhost:8443 -k

# 清理
docker rm -f multi-port

7.9 本章小结

网络模式 特点 适用场景
bridge 默认模式,NAT 转换 单机多容器
host 共享宿主机网络栈 高性能需求
none 完全隔离 安全敏感场景
overlay 跨主机通信 Swarm/Kubernetes
macvlan 独立 MAC 地址 需要独立 IP 的场景

7.10 课后练习

  1. 基础题:创建自定义网络,启动两个容器,验证 DNS 解析功能。
  2. 进阶题:配置前后端分离的应用网络(frontend + backend)。
  3. 排错题:故意制造网络故障(断开网络、修改 DNS),练习排查步骤。

📖 下一章:Docker 数据持久化 ------ 掌握容器数据的存储和管理

相关推荐
深盾科技_Virbox1 小时前
Virbox Protector 从何而来:深盾科技的软件保护演进
运维·数据库·科技
是个西兰花1 小时前
Linux:进程信号
linux·运维·服务器
云飞云共享云桌面1 小时前
智能装备制造数字化实测:10人SolidWorks云桌面部署,云飞云方案替代传统单机工作站
运维·服务器·网络·人工智能·制造
Urbano1 小时前
突破品类边界:数控模板机不止制衣,枕套等家居家纺自动化生产全科普
运维·自动化
CS创新实验室1 小时前
从“业余爱好”到数字基石:Linux 发展史及带给技术人的成长启示
linux·运维·服务器
江畔柳前堤1 小时前
第17章:Docker 大厂面试题精选(腾讯/阿里/字节/美团)
运维·网络·spring cloud·docker·容器·eureka
Biomamba生信基地1 小时前
FindNeighbors()函数报错object ‘CsparseMatrix_validate’ not found
linux·运维·服务器·生物信息学
AI-好学者1 小时前
RAG知识点_3_高级实践
人工智能·ai·架构·langchain·ai编程
AI视频剪辑官1 小时前
播客切片工具选型核心评价维度
网络·人工智能·算法