第07章:Docker 网络模型

发布时间:2026/7/2 20:25:16
第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 查看网络# 列出所有 Docker 网络dockernetworkls# NETWORK ID NAME DRIVER SCOPE# abc123def456 bridge bridge local# def456abc123 host host local# ghi789jkl012 none null local# 查看网络详细信息dockernetwork inspect bridge# 查看容器的网络配置dockerinspect--format{{json .NetworkSettings.Networks}}container7.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 │ │ │ └──────────────────────┬───────────────────────┘ │ │ │ │ └───────────────────────────┼──────────────────────────┘ │ ┌────┴────┐ │ 路由器 │ └────┬────┘ │ ┌────┴────┐ │ 互联网 │ └─────────┘# 使用默认 bridge 网络dockerrun-d--nameweb1 nginxdockerrun-d--nameweb2 nginx# 查看容器 IPdockerinspect--format{{.NetworkSettings.IPAddress}}web1# 172.17.0.2dockerinspect--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 ││ │ └───────────────┬──────────────────────────┘│ │ │ │ └──────────────────┼─────────────────────────────┘ │ ┌────┴────┐ │ 路由器 │ └─────────┘# 使用 host 网络dockerrun-d--networkhost--nameweb nginx# 容器直接使用宿主机的网络# Nginx 监听宿主机的 80 端口# 访问宿主机 IP:80 即可访问# 查看容器网络dockerinspect--format{{.NetworkSettings.Networks}}web# map[host:0xc000123456]# host 网络的特点# ✅ 性能最好没有 NAT 转换# ✅ 网络配置简单# ❌ 端口冲突风险多个容器不能监听同一端口# ❌ 网络隔离性差7.2.3 none无网络# 使用 none 网络完全隔离dockerrun-d--networknone--nameisolated nginx# 容器只有 loopback 接口dockerexecisolatedipaddr# 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 │ │ │ └───────────────────────┘ │ │ └───────────────────────┘ │ └────────────────────────────┘ └────────────────────────────┘# 创建 swarm 集群overlay 需要 swarm 模式dockerswarm init# 创建 overlay 网络dockernetwork create-doverlay my-overlay# 在 swarm 服务中使用 overlay 网络dockerservicecreate--nameweb--networkmy-overlay nginx# overlay 网络的特点# ✅ 支持跨主机容器通信# ✅ 自动 DNS 解析# ✅ 支持服务发现# ❌ 需要 Docker Swarm 或外部存储如 Consul7.2.5 macvlanMAC 地址虚拟化# macvlan 让容器拥有独立的 MAC 地址# 容器在网络中就像独立的物理设备# 创建 macvlan 网络dockernetwork create-dmacvlan\--subnet192.168.1.0/24\--gateway192.168.1.1\-oparenteth0\my-macvlan# 使用 macvlan 网络dockerrun-d--networkmy-macvlan--ip192.168.1.100--nameweb nginx# macvlan 的特点# ✅ 容器有独立的 IP 和 MAC 地址# ✅ 性能好无 NAT# ❌ 需要物理网络支持# ❌ 配置复杂7.3 自定义网络7.3.1 创建自定义网络# 创建 bridge 类型的自定义网络dockernetwork create my-network# 创建并配置参数dockernetwork create\--driverbridge\--subnet192.168.100.0/24\--gateway192.168.100.1\--ip-range192.168.100.0/25\--optcom.docker.network.bridge.namemy-bridge\my-network# 查看网络详情dockernetwork inspect my-network7.3.2 自定义网络的优势# 1. 自动 DNS 解析关键优势dockernetwork create my-netdockerrun-d--nameweb-server--networkmy-net nginxdockerrun-d--nameapp-server--networkmy-net myapp# app-server 容器内可以直接通过 web-server 名称访问# curl http://web-server:80 ✅ 自动解析# 2. 更好的隔离性dockernetwork create net-adockernetwork create net-bdockerrun-d--nameweb--networknet-a nginxdockerrun-d--nameapp--networknet-b myapp# web 和 app 互相隔离不能通信# 3. 灵活的网络配置dockernetwork create\--subnet10.10.0.0/16\--ipv6\my-network-v67.3.3 将容器连接到多个网络# 一个容器可以连接到多个网络dockernetwork create front-netdockernetwork create back-netdockerrun-d--nameweb--networkfront-net nginxdockerrun-d--nameapp--networkback-net myapp# 动态添加网络连接dockernetwork connect back-net web# 现在 web 同时连接 front-net 和 back-net# web 可以与两个网络中的容器通信# 动态断开网络连接dockernetwork disconnect back-net web7.4 容器 DNS 解析7.4.1 自定义网络中的 DNS# 创建自定义网络dockernetwork create app-net# 启动多个容器dockerrun-d--namedb--networkapp-net mysql:8.0dockerrun-d--nameredis--networkapp-net redis:7dockerrun-d--nameweb--networkapp-net myapp# 在 web 容器中可以直接使用容器名访问dockerexecwebpingdb# ✅ 解析到 db 容器的 IPdockerexecwebpingredis# ✅ 解析到 redis 容器的 IP# 还可以使用网络别名dockerrun-d--namedb-primary--networkapp-net\--network-alias primary-db\mysql:8.0# 使用别名访问dockerexecwebpingprimary-db# ✅ 解析到 db-primary 容器7.4.2 DNS 配置# 自定义 DNS 服务器dockerrun-d--dns8.8.8.8--dns8.8.4.4 nginx# 自定义 DNS 搜索域dockerrun-d--dns-search example.com nginx# 自定义 hosts 文件dockerrun-d--add-host myhost:192.168.1.100 nginx# 查看容器的 DNS 配置dockerexeccontainercat/etc/resolv.conf7.5 端口映射详解7.5.1 端口映射语法# 基本语法dockerrun-d-phost_port:container_portnginx# 多端口映射dockerrun-d\-p80:80\-p443:443\-p8080:8080\nginx# 指定协议dockerrun-d-p80:80/tcp-p80:80/udp nginx# 指定绑定地址dockerrun-d-p127.0.0.1:8080:80 nginx# 仅本机访问dockerrun-d-p0.0.0.0:8080:80 nginx# 所有地址默认dockerrun-d-p192.168.1.100:8080:80 nginx# 指定网卡# 随机端口dockerrun-d-Pnginx# 映射 EXPOSE 的所有端口dockerrun-d-p80nginx# 主机随机端口 → 容器 80# 查看端口映射dockerportcontainer# 80/tcp - 0.0.0.0:80807.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 端口# 查看 iptables 规则了解底层原理sudoiptables-tnat-L-n|grep8080# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:807.6 容器间通信实战7.6.1 同一网络中的容器通信# 创建应用网络dockernetwork create app-net# 启动 MySQL 数据库dockerrun-d\--namemysql-db\--networkapp-net\-eMYSQL_ROOT_PASSWORDsecret123\-eMYSQL_DATABASEmyapp\mysql:8.0# 启动 Redis 缓存dockerrun-d\--nameredis-cache\--networkapp-net\redis:7# 启动应用dockerrun-d\--nameweb-app\--networkapp-net\-p8080:8080\-eDB_HOSTmysql-db\-eDB_PORT3306\-eREDIS_HOSTredis-cache\-eREDIS_PORT6379\myapp:latest# 在 web-app 容器内测试连接dockerexecweb-apppingmysql-db# ✅dockerexecweb-apppingredis-cache# ✅7.6.2 跨网络通信# 创建前后端网络dockernetwork create frontenddockernetwork create backend# 启动 Nginx前端dockerrun-d\--namenginx\--networkfrontend\-p80:80\nginx# 启动应用前后端都连接dockerrun-d\--nameapi-server\--networkbackend\myapi:latest# 将 nginx 连接到 backend 网络dockernetwork connect backend nginx# 现在 nginx 可以通过 api-server:8080 访问后端# 但外部网络只能访问 nginx无法直接访问 api-server7.7 网络故障排查7.7.1 常用排查命令# 1. 查看容器网络配置dockerinspect--format{{json .NetworkSettings}}container# 2. 进入容器检查网络dockerexec-itcontaineripaddrdockerexec-itcontaineriproutedockerexec-itcontainercat/etc/resolv.conf# 3. 测试网络连通性dockerexec-itcontainerpingtargetdockerexec-itcontainercurl-vhttp://target:port# 4. 查看 Docker 网络dockernetworklsdockernetwork inspectnetwork# 5. 查看 iptables 规则sudoiptables-tnat-L-nsudoiptables-L-n7.7.2 常见网络问题问题可能原因解决方案容器间无法通信不在同一网络连接到同一网络无法通过名称访问使用了默认 bridge使用自定义网络端口映射不生效防火墙/iptables检查防火墙规则DNS 解析失败DNS 配置错误检查 /etc/resolv.conf容器无法上网网络配置问题检查网桥和路由7.8 动手实验实验 7.1网络模式对比# 1. bridge 模式默认dockerrun-d--namebridge-test nginxdockerinspect--format{{.NetworkSettings.Networks}}bridge-test# map[bridge:...]# 2. host 模式dockerrun-d--namehost-test--networkhostnginxdockerinspect--format{{.NetworkSettings.Networks}}host-test# map[host:...]# 3. none 模式dockerrun-d--namenone-test--networknone nginxdockerexecnone-testipaddr# 只有 lo 接口# 清理dockerrm-fbridge-test host-test none-test实验 7.2自定义网络 DNS 解析# 1. 创建自定义网络dockernetwork create demo-net# 2. 启动服务器容器dockerrun-d--nameserver1--networkdemo-net nginxdockerrun-d--nameserver2--networkdemo-net nginx# 3. 在 server1 中测试 DNS 解析dockerexecserver1pingserver2# PING server2 (172.18.0.3): 56 data bytes# 64 bytes from 172.18.0.3: seq0 ttl64 time0.089 ms# 4. 使用网络别名dockerrun-d--nameserver3--networkdemo-net --network-alias myserver nginxdockerexecserver1pingmyserver# ✅ 解析到 server3# 清理dockerrm-fserver1 server2 server3dockernetworkrmdemo-net实验 7.3端口映射# 1. 多端口映射dockerrun-d--namemulti-port\-p8080:80\-p8443:443\-p8081:8080\nginx# 2. 查看端口映射dockerport multi-port# 80/tcp - 0.0.0.0:8080# 443/tcp - 0.0.0.0:8443# 8080/tcp - 0.0.0.0:8081# 3. 测试访问curlhttp://localhost:8080curlhttps://localhost:8443-k# 清理dockerrm-fmulti-port7.9 本章小结网络模式特点适用场景bridge默认模式NAT 转换单机多容器host共享宿主机网络栈高性能需求none完全隔离安全敏感场景overlay跨主机通信Swarm/Kubernetesmacvlan独立 MAC 地址需要独立 IP 的场景7.10 课后练习基础题创建自定义网络启动两个容器验证 DNS 解析功能。进阶题配置前后端分离的应用网络frontend backend。排错题故意制造网络故障断开网络、修改 DNS练习排查步骤。 下一章Docker 数据持久化 —— 掌握容器数据的存储和管理