Docker 网络与通讯

1 阅读4分钟

Docker 默认网络

核心概念 —— docker0、veth-pair

docker0 —— 虚拟交换机

什么是 docker0:docker0 是一个虚拟桥接网络,即虚拟交换机。

veth-pair 技术

它是一对虚拟的、点对点直接链路。

把这两句串起来理解整个过程:

宿主机
  ├── docker0(虚拟交换机,有自己的 IP,通常是 172.17.0.1)
  │
  ├── veth 一对网线的一端  ←→  容器里的 eth0(网线的另一端)
  ├── veth 一对网线的一端  ←→  容器里的 eth0
  └── ...

所以:
· 每个容器都有一根"虚拟网线"(veth-pair)插到 docker0 这个虚拟交换机上
· 同一台宿主机上的容器,通过 docker0 二层互通

实操验证:看容器的网卡和 IP

docker run -d --name tomcat01 -P tomcat:7
docker run -d --name tomcat02 -P tomcat:7

docker exec tomcat01 ip addr          # 容器里有一块 eth0,IP 形如 172.17.0.x
docker inspect -f '{{.NetworkSettings.IPAddress}}' tomcat01
docker inspect -f '{{.NetworkSettings.IPAddress}}' tomcat02

ip addr show docker0                  # 宿主机上的 docker0,IP 通常是 172.17.0.1

注意:这两条 docker run 用的是 -P(大写),也就是让 Docker 随机分配宿主机端口。用 docker port tomcat01 可以看到实际映射到了哪个端口(一般是 32768 起)。


四种网络模式

模式DRIVER说明
Bridgebridge默认模式(桥接,自己创建的网络也是用它)。此模式会为每一个容器分配、设置 IP 等,并将容器连接到一个 docker0 虚拟网桥,通过 docker0 网桥以及 iptables nat 表配置与宿主机通信
Hosthost容器没有独立网络命名空间,不会虚拟出自己的网卡、也不配置独立 IP,而是直接使用宿主机的 IP 和端口
Nonenull该模式关闭了容器的网络功能(一般不用)
自定义(container)—加入另一个已存在容器的网络命名空间(了解即可)

Host 模式要注意什么:因为直接用宿主机网络,所以不能做端口映射(-p 会失效并可能报错),而且容器里 ss -lntp 看到的是宿主机所有的端口。适合做网络性能敏感的场景(少了 NAT 一层)。

None 模式:给了你一个完全没有网络的容器,通常用于"我自己来配网络"的高级场景,或者做纯计算任务。


自定义网络

现有的网络模式不一定适合所有场景,有时候我们要自定义一个网络。

docker network create --driver bridge --subnet 192.168.100.0/24 --gateway 192.168.100.1 hangnet
docker run -d -P --name=tomcat04 --net hangnet tomcat:7
docker run -d -P --name=tomcat05 --net hangnet tomcat:7

检验(这一步很关键):

docker network ls                                    # 能看到 hangnet
docker network inspect hangnet | grep -A3 Subnet     # 能看到 192.168.100.0/24
docker inspect -f '{{.NetworkSettings.IPAddress}}' tomcat04   # 192.168.100.x
docker inspect -f '{{.NetworkSettings.IPAddress}}' tomcat05

# ★ 关键验证:同一个自定义网络里,容器可以互相 ping 通(默认用容器名就能通)
docker exec tomcat04 ping -c 2 tomcat05

★ 自定义网络 vs 默认 bridge 网络 —— 最重要的一个区别:

对比项默认 bridge自定义网络(bridge driver)
容器之间能否用容器名通信不能(只能靠 IP,而且 IP 会变)能(内置 DNS 解析)
网段固定 172.17.0.0/16自己指定
隔离所有容器混在一起按网络隔离,不同网络不互通

清理实验环境:

docker rm -f tomcat01 tomcat02 tomcat04 tomcat05
docker network rm hangnet

容器对外服务(SNAT / DNAT)

① 容器可以上网的原理,是利用 iptables 的 SNAT 技术(SNAT = 源地址转换)。

② 容器服务能被外部访问,是利用了 iptables 的 DNAT 技术(DNAT = 目标地址转换)。

【出方向 / 容器访问外网 → SNAT(源地址转换)】
  容器(172.17.0.3) → 请求发到 docker0 → 宿主机把【源地址】改成自己的 IP
  → 发到外网 → 回包回到宿主机 → 宿主机再转回容器
  为什么必须改:172.17.0.3 是私网地址,外网不知道怎么回包

【入方向 / 外部访问容器 → DNAT(目标地址转换)】
  外部用户访问 宿主机IP:8080
  → PREROUTING 链上被 DOCKER 链匹配到
  → 把【目标地址】改成 172.17.0.3:80
  → 转给容器,容器以为是直接连它
  这就是 -p 8080:80 背后真正发生的事