5.2 自定义网络与容器间通信


5.2 自定义网络与容器间通信

本节摘要:组建船队的核心手艺——自定义桥接网络里,容器名就是域名。本节完成主线任务的通信半场:建网、接网、容器名互访的全流程实验,并讲清默认桥接网络为什么不能拿来跑业务互联。

两只箱子怎么找到彼此

主线任务:Web 箱子要连数据库箱子。第一直觉是记 IP,但 IP 在容器世界是易变的——容器重建就换号。确定性方案是让引擎帮你做名字解析:同一个自定义网络里,容器名就是可解析的域名。这是本章最重要的一个机制。

先看反例——默认 bridge 网络里名字解析不工作:

# 建两只容器(不指定网络,落进默认 bridge) docker run -d --name app-legacy -p 8080:80 nginx:1.25-alpine docker run -d --name db-legacy redis:7-alpine # 从 app 箱里 ping 数据库的"名字"——失败! docker exec app-legacy ping -c 1 db-legacy # ping: bad address 'db-legacy' # 默认 bridge 没有内建域名解析,只能用 IP(而 IP 会漂移)

再看正解——自定义网络里的名字互访。完整走一遍建队流程:

# 第一步:建一条自定义航道(业务泊位区) docker network create --driver bridge fleet-net # 输出网络 ID:2b3c4d5e6f7a... # 第二步:两只箱子接进同一条航道 docker run -d --name fleet-db --network fleet-net redis:7-alpine docker run -d --name fleet-app --network fleet-net nginx:1.25-alpine # 第三步:用容器名直接互访——引擎内建 DNS 在工作 docker exec fleet-app ping -c 1 fleet-db # PING fleet-db (172.18.0.2): 56 data bytes # 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.089 ms # 名字 fleet-db 被解析成同网络的容器内网地址

同一个容器名,被引擎解析成同航道内网地址——通信不再依赖 IP,重建容器也不破坏互联(新容器顶同名进航道,名字照旧解析)。第 6 章的 Compose 会把这个模式自动化:声明文件里同一网络的多个服务天然互访。

航道管理三件事

查: 查一条航道上有谁、各自什么地址:

# 查看航道详情(重点看 Containers 段) docker network inspect fleet-net --format "{{range .Containers}}{{.Name}} {{end}}" # fleet-app fleet-db

调: 运行中的容器动态接入或退出航道(不用重建容器):

# 起一只监控箱子,动态接入业务航道 docker run -d --name fleet-mon nginx:1.25-alpine docker network connect fleet-net fleet-mon docker exec fleet-mon ping -c 1 fleet-app # 通了 —— connect 无需重启任何容器 # 不需要时退出航道 docker network disconnect fleet-net fleet-mon

拆: 航道空了才能拆:

# 拆除前先清空航道成员(或成员已全部拆除) docker network rm fleet-net # (有容器接入时会报错:network has active endpoints,先 disconnect)

顺带认识航道自身的规划参数:建网时可以显式指定网段与网关,不指定则引擎自动从私有网段里划一块。多条航道并存、或宿主机本身处在公司内网时,显式规划能避免容器网段与办公网段撞车——这是在办公室环境调试容器时真实会踩的坑:

# 建网时显式规划网段,避开既有内网 docker network create --driver bridge \ --subnet 172.31.0.0/16 --gateway 172.31.0.1 plan-net

端到端验收:船队通信演习

把主线任务的通信半场完整演一遍——Web 箱访问数据库箱子的真实服务端口:

# 组队:同一条航道上的应用与数据库 docker network create drill-net docker run -d --name drill-db --network drill-net \ -e REDIS_PASSWORD=drillpass redis:7-alpine \ redis-server --requirepass drillpass docker run -d --name drill-app --network drill-net nginx:1.25-alpine # 演习:从应用箱子测数据库箱子的服务端口(6379) docker exec drill-app sh -c \ "nc -zv drill-db 6379" # drill-db (172.19.0.2:6379) open # 端口通 —— 应用配置里写数据库地址就填容器名 drill-db

两个工程细节补在最后。其一,泊位映射与航道互联是两回事-p 管外部世界进港,航道内互联根本不需要 -p——数据库箱子对内提供服务时不发布任何泊位,天然不暴露给宿主机以外,这是自定义网络的额外安全红利。其二,名字解析只在自定义网络可用,第 6 章会看到 Compose 建的项目网络就是自定义网络,这就是"服务名即主机名"的技术来源。

再送一个进阶小件:网络别名。同一只箱子在一条航道里可以有多个名字,用 --network-alias 挂上——解析时会自动在这些别名间轮转。这是"无感知换箱"的雏形:新旧两只箱子挂同一个别名,访问方无感切换。今天只需记住这个能力存在,第 6 章的编队模式会把它用得更自然。

# 给容器挂一个业务别名(谁解析这个别名,谁就能找到这只箱子) docker run -d --name fleet-app --network fleet-net \ --network-alias order-api nginx:1.25-alpine

本节要点回顾

  • 自定义网络里容器名就是域名,由引擎内建解析;默认 bridge 无此能力,别拿它跑业务互联。
  • 建队三步:network create、run 时 --network 接入、容器名互访验证。
  • 动态调队:network connect 或 disconnect 在线加减成员,无需重建容器。
  • 航道内互联不占用泊位:数据库不配 -p 就不对外暴露,安全白赚。
  • 名字即地址让通信与重建解耦——这是多容器工程确定性的基石。

通信半场完成,接下来是持久化半场:让数据比箱子活得久。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U