第二部分-Docker核心原理——10. 容器网络原理
10. 容器网络原理1. 容器网络概述容器网络是 Docker 的核心组件之一负责实现容器与容器、容器与宿主机、容器与外部的网络通信。Docker 通过 Linux 内核的网络命名空间、veth pair、网桥、iptables 等技术实现网络隔离和连通。┌─────────────────────────────────────────────────────────────┐ │ Docker 网络架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 宿主机 │ │ │ │ │ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ │ │ 容器A │ │ 容器B │ │ 容器C │ │ │ │ │ │ eth0 │ │ eth0 │ │ eth0 │ │ │ │ │ │172.17.0.2│ │172.17.0.3│ │172.17.0.4│ │ │ │ │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ │ │ │ │ │ │ │ veth │ veth │ veth │ │ │ │ ▼ ▼ ▼ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ docker0 网桥 │ │ │ │ │ │ 172.17.0.1/16 │ │ │ │ │ └─────────────────────┬───────────────────────┘ │ │ │ │ │ │ │ │ │ │ iptables NAT │ │ │ │ ▼ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ eth0 (宿主机网卡) │ │ │ │ │ │ 192.168.1.100 │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────┐ │ │ │ 外部网络 │ │ │ └─────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘2. Docker 网络模式网络模式说明使用场景bridge默认模式通过 docker0 网桥通信大多数场景host共享宿主机网络栈网络性能要求高none无网络不需要网络container共享其他容器网络网络调试overlay跨主机网络Swarm 集群macvlan直接使用物理网卡需要物理网络 IP3. Bridge 网络模式3.1 原理┌─────────────────────────────────────────────────────────────┐ │ Bridge 模式原理 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 步骤 │ │ 1. 创建网络命名空间 │ │ 2. 创建 veth pair 虚拟网卡对 │ │ 3. 一端放入容器命名空间eth0 │ │ 4. 另一端挂载到 docker0 网桥 │ │ 5. 分配 IP 地址默认 172.17.0.0/16 │ │ 6. 设置 iptables NAT 规则实现外网访问 │ │ │ └─────────────────────────────────────────────────────────────┘3.2 查看网桥信息# 查看 docker0 网桥ipaddr show docker0# 查看网桥设备brctl show# 查看 iptables NAT 规则sudoiptables-tnat-L-n-v# 查看 FORWARD 规则sudoiptables-LFORWARD-n-v# 查看网络命名空间lsns-tnet# 查看容器网络详细信息dockerinspect container_name|grep-A20Networks3.3 自定义 bridge 网络# 创建自定义 bridge 网络dockernetwork create--driverbridge--subnet10.10.0.0/16--gateway10.10.0.1 mynet# 查看网络列表dockernetworkls# 查看网络详情dockernetwork inspect mynet# 在自定义网络中运行容器dockerrun-d--nameapp1--networkmynet nginxdockerrun-d--nameapp2--networkmynet nginx# 容器间可以通过名称通信自动 DNS 解析dockerexecapp1pingapp2# 连接容器到指定网络dockernetwork connect mynet app1# 断开连接dockernetwork disconnect mynet app1# 删除网络dockernetworkrmmynet4. Host 网络模式# 使用 host 网络模式dockerrun-d--networkhost--nameweb nginx# 容器直接使用宿主机网络没有独立 IP# 容器内的 localhost 就是宿主机的 localhostdockerexecwebcurllocalhost:80# 查看网络与宿主机相同dockerexecwebipaddr# 端口映射不需要 -p 参数容器端口直接绑定宿主机dockerrun-d--networkhostnginx# 占用宿主机 80 端口# 优点网络性能最佳# 缺点端口冲突隔离性差# 查看哪些容器使用 host 网络dockerps--formattable {{.Names}}\t{{.Ports}}|grep-v0.0.0.05. None 网络模式# 容器没有网络dockerrun-it--networknone alpinesh# 只有 lo 接口/# ip addr# 1: lo: ...# 适用场景# - 不需要网络的批处理任务# - 安全隔离要求高# - 自定义网络配置# 后续可以手动连接网络dockernetwork connect bridge container_name6. Container 网络模式# 创建第一个容器dockerrun-d--nameweb1 nginx# 第二个容器共享第一个容器的网络dockerrun-it--networkcontainer:web1--nameweb2 alpinesh# web2 中使用 localhost 访问 web1/# curl localhost:80# 查看网络和 web1 相同/# ip addr# 适用场景# - 网络调试# - 网络代理# - Sidecar 模式7. veth pair 工作原理┌─────────────────────────────────────────────────────────────┐ │ veth pair 原理 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 宿主机 容器 │ │ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ │ │ │ │ docker0 │ │ eth0 │ │ │ │ 172.17.0.1 │ │ 172.17.0.2 │ │ │ │ │ │ │ ▲ │ │ │ │ │ │ │ │ │ │ │ │ ▼ │ │ │ │ │ │ │ ┌───────┐ │ │ │ │ │ │ │ │ veth │─────┼───────────────┼───────┘ │ │ │ │ │ pair │ │ │ │ │ │ │ └───────┘ │ │ │ │ │ │ │ │ │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ │ veth 特点 │ │ - 成对出现的虚拟网卡 │ │ - 一端在容器一端在宿主机 │ │ - 数据包在两端直接转发 │ │ │ └─────────────────────────────────────────────────────────────┘# 查看 veth pair# 创建容器dockerrun-d--nametestnginx# 获取容器 PIDPID$(dockerinspect-f{{.State.Pid}}test)# 查看容器的网络接口nsenter-t$PID-niplink# 查看宿主机上的 vethiplink|grepveth# 查看 veth 配对关系# 方法1通过索引dockerexectestcat/sys/class/net/eth0/iflinkiplink|grep$(dockerexectestcat/sys/class/net/eth0/iflink)# 方法2使用 ethtoolethtool-SvethXXXX8. iptables 与端口映射8.1 NAT 原理# 容器访问外网SNATdockerrun-d--nameweb nginxdockerexecwebcurlgoogle.com# 查看 SNAT 规则sudoiptables-tnat-LPOSTROUTING-n-v# MASQUERADE 规则# 外网访问容器DNATdockerrun-d-p8080:80 nginx# 查看 DNAT 规则sudoiptables-tnat-LPREROUTING-n-vsudoiptables-tnat-LDOCKER-n-v# 查看具体映射iptables-tnat-LDOCKER --line-numbers iptables-tfilter-LDOCKER --line-numbers8.2 端口映射详解# 映射到指定端口dockerrun-d-p8080:80 nginx# 映射到随机端口dockerrun-d-p80nginxdockerport container_name# 映射 UDP 端口dockerrun-d-p53:53/udp nginx# 映射特定 IPdockerrun-d-p127.0.0.1:8080:80 nginx# 映射端口范围dockerrun-d-p8080-8082:80-82 nginx# 查看端口映射dockerport container_namedockerinspect container_name|grep-A10PortBindings9. 容器间通信9.1 同一网络通信# 创建网络dockernetwork create app-net# 启动服务dockerrun-d--networkapp-net--namemysql-eMYSQL_ROOT_PASSWORD123mysqldockerrun-d--networkapp-net--nameapp-p8080:8080 myapp# 通过容器名通信dockerexecapppingmysql# 通过网络别名通信dockernetwork create--subnet10.10.0.0/16 app-net2dockerrun-d--networkapp-net2 --network-alias api myapp9.2 不同网络通信# 容器连接到多个网络dockernetwork create net1dockernetwork create net2dockerrun-d--namerouter--networknet1 alpinedockernetwork connect net2 router# 使用 docker network connect 连接dockernetwork connect net1 container210. 网络命名空间操作# 进入容器网络命名空间CONTAINER_PID$(dockerinspect-f{{.State.Pid}}container_name)sudonsenter-t$CONTAINER_PID-nbash# 查看网络配置ipaddriproutecat/etc/resolv.conf# 使用 ip netns需要链接PID$(dockerinspect-f{{.State.Pid}}container_name)sudoln-s/proc/$PID/ns/net /var/run/netns/$PIDipnetns listipnetnsexec$PIDipaddr11. 网络故障排查11.1 常用命令# 检查容器网络配置dockerinspect container_name|grep-A20Networks# 在容器内测试网络dockerexeccontainer_namepinggoogle.comdockerexeccontainer_namecurl-vhttp://example.comdockerexeccontainer_namenslookupgoogle.com# 检查宿主机网络dockernetworklsdockernetwork inspect bridge brctl showiproute# 检查 iptablessudoiptables-L-n-vsudoiptables-tnat-L-n-v# 跟踪网络包dockerexeccontainer_name tcpdump-ieth0 tcpdump-idocker011.2 常见问题解决# 问题1容器无法访问外网# 检查 NAT 规则sudoiptables-tnat-LPOSTROUTING-n-v# 检查 IP 转发sysctlnet.ipv4.ip_forward# 开启转发sudosysctl-wnet.ipv4.ip_forward1# 问题2端口映射不生效# 检查 docker-proxypsaux|grepdocker-proxy# 检查 iptables 规则sudoiptables-tnat-LDOCKER-n-v# 问题3容器间无法通信# 检查 docker0 网桥iplinkshow docker0# 检查防火墙规则sudoufw status12. 网络性能优化# 使用 host 网络模式性能最优dockerrun-d--networkhostnginx# 使用 macvlan 模式直接使用物理网络dockernetwork create-dmacvlan\--subnet192.168.1.0/24\--gateway192.168.1.1\-oparenteth0\macnetdockerrun-d--networkmacnet--ip192.168.1.200 nginx# 调整网桥 MTUdockernetwork create--optcom.docker.network.driver.mtu1450mynet# 禁用 iptables不推荐# /etc/docker/daemon.json{iptables:false}13. 常用命令速查操作命令查看网络docker network ls创建网络docker network create查看详情docker network inspect连接网络docker network connect断开网络docker network disconnect删除网络docker network rm查看端口docker port查看网桥brctl show查看规则iptables -L -n -v14. 常见问题Q1: 容器如何访问宿主机服务# 使用 host.docker.internalMac/Windows# 使用宿主机 IPLinux# 或使用 --network host 模式Q2: 两个容器如何共享网络# 使用 container 模式dockerrun--networkcontainer:container2Q3: 容器重启后 IP 会变吗默认 bridge 网络会变自定义网络使用 --ip 固定 IP。15. 小结Bridge 模式默认网络通过 docker0 网桥通信Host 模式共享宿主机网络性能最佳None 模式无网络完全隔离Container 模式共享其他容器网络veth pair实现容器与网桥的连接iptables实现 NAT 和端口映射自定义网络支持容器名解析掌握网络排查工具和命令
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2596250.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!