docker容器如何相互通讯?容器又是如何访问外部网络的?

这是一个非常经典且核心的 Docker 网络面试题。搞懂这个,你就能明白为什么有时候容器能 ping 通百度,却 ping 不通隔壁的数据库。

Docker 的网络模型可以想象成一个 “国中之国”。宿主机(你的电脑)是“大国”,Docker 引擎在里面建了一个“小国”(虚拟子网)。

我们分两个场景来讲:内政(容器互通)外交(容器与外界互通)


1. 容器之间怎么通讯?(内政)

默认情况下,容器运行在 Bridge 模式(网桥模式)。

🧱 核心设施:虚拟交换机 (docker0)

当 Docker 启动时,它会在宿主机上安装一个虚拟的“网线交换机”,名字通常叫 docker0

  • 所有容器启动时,都会被插一根虚拟网线(veth pair)到这个 docker0 交换机上。
  • docker0 会给每个容器发一个内部 IP(比如 172.17.0.2, 172.17.0.3...)。

📡 通讯方式 A:通过 IP 直连

  • 原理:因为大家都在同一个交换机(docker0)下,容器 A 只要知道容器 B 的 IP,喊一声就能听到(ARP广播)。
  • 缺点:容器重启后 IP 会变!你不可能在代码里写死 172.17.0.x

📡 通讯方式 B:通过服务名(DNS 自动发现)—— 推荐

这就是 docker-compose 的魔法所在。

  • 原理:Docker 引擎内置了一个微型 DNS 服务器。
  • 流程
  1. 你的 Scheduler 容器想找 Jenkins,发请求给 http://jenkins:8080
  2. 请求先被 Docker 的内置 DNS 拦截。
  3. DNS 查表:“哦,jenkins 这个名字对应的容器现在的 IP 是 172.18.0.5”。
  4. 自动把请求转发到 172.18.0.5:8080
  • 场景:这就是为什么在你的 docker-compose.yml 里,Scheduler 只要写 http://jenkins 就能连上,完全不用管 IP。

2. 容器和外界怎么通讯?(外交)

这里分为 “出去”“进来” 两个方向。

📤 方向一:容器访问互联网(Outbound)

比如你的 Runner 容器里执行 pip install requests,需要去外网下载包。

  • 机制:NAT (网络地址转换) / IP 伪装
  • 过程
  1. 容器:我想访问 8.8.8.8(Google)。
  2. docker0:发现这是外网地址,把它丢给宿主机。
  3. 宿主机(路由器):开启了 IP 转发功能。它把数据包抓过来,把 源 IP172.17.0.x(内部 IP)悄悄改成 宿主机 eth0 的 IP(比如 192.168.1.100)。这叫 SNAT (Source NAT)
  4. 路由器/公网:看到的是宿主机在发请求,于是把数据回传给宿主机。
  5. 宿主机:收到回包,查表发现是刚才那个容器发的,再把包转回给容器。
  • 结论:容器默认就能“出去”上网,靠的是宿主机当它的代理人。

📥 方向二:外界访问容器(Inbound)

比如你在浏览器里访问 Jenkins 的网页 http://localhost:8080

  • 机制:端口映射 (Port Mapping)
  • 过程
  1. 容器里的 Jenkins 监听的是容器内的 :8080。外界根本访问不到 172.x.x.x 这个私有网段。
  2. 我们在启动时使用了 -p 8080:8080
  3. Docker 进程(准确说是 docker-proxy 或者 iptables 规则)会在 宿主机的 8080 端口 进行监听。
  4. 当你访问宿主机 8080 时,流量被 Docker 拦截,通过 DNAT (Destination NAT) 强行把 目标 IP/端口 修改为 容器IP:8080,然后扔进 docker0 网桥。
  • 结论:外界想进来,必须在宿主机“开门”(映射端口)。如果没有 -p,容器就是一座孤岛,只能出去,进不来。

📝 总结图谱 (面试脑图)

通讯场景 核心技术 关键命令/配置 类比
容器 <-> 容器 Bridge (网桥) + DNS docker-compose 服务名 公司内线电话,直拨分机号(名字)
容器 -> 外网 SNAT (源地址转换) 默认开启 (IP Forwarding) 员工通过公司总出口访问百度
外网 -> 容器 DNAT (端口映射) -p 8080:80 公司前台转接,打总机转给某员工

这就是为什么在 Host 模式 下快的原因:因为没有了中间的 NAT 转换和网桥转发,容器直接用宿主机的网卡,少了两层“手续”。

posted @ 2026-02-03 22:51  CalvinMax  阅读(1)  评论(0)    收藏  举报