4. 自定义Bridge网络:创建与管理自定义网络、容器互联、DNS解析

Docker 默认的 bridge 网络虽然开箱即用,但在生产环境或复杂微服务场景下,其局限性非常明显:容器只能通过 IP 地址通信,且无法实现服务发现。自定义 Bridge 网络正是为了解决这些问题而设计的,它提供了内置的 DNS 解析能力,允许容器通过容器名直接互联,是构建容器化应用网络的基础设施。

4.1 自定义Bridge网络 vs 默认Bridge网络

在深入操作之前,先明确自定义 Bridge 网络相比默认网络的核心优势:

对比维度 默认 Bridge 网络 自定义 Bridge 网络
DNS 解析 不支持容器名解析,只能通过 --link 单向连接 内置 DNS,自动解析所有容器名到对应 IP
网络隔离 所有未指定网络的容器默认加入,隔离性差 独立网络空间,只有加入该网络的容器才能通信
动态加入/离开 容器重启后 IP 可能变化,需手动维护 支持动态连接和断开,DNS 自动更新
配置灵活性 仅支持默认子网,无法自定义网段 可指定子网、网关、IP 范围
适用场景 单机简单测试,容器间无强依赖 微服务架构、多容器协作、需要服务发现的场景
最佳实践: 在生产环境中,始终优先使用自定义 Bridge 网络而非默认网络。即使只有一个应用需要多个容器协作,自定义网络带来的 DNS 解析能力也能大幅简化配置管理。

4.2 创建与管理自定义Bridge网络

Docker 提供了 docker network 命令族来管理网络资源。以下是创建和管理自定义 Bridge 网络的完整流程。

4.2.1 创建网络

使用 docker network create 命令创建自定义 Bridge 网络。最简形式只需指定网络名称:

# 创建默认配置的自定义网络
docker network create my-net

# 创建时指定子网和网关
docker network create --subnet=172.20.0.0/16 --gateway=172.20.0.1 my-net-prod

# 创建时指定 IP 范围(限制自动分配的 IP 池)
docker network create --subnet=172.20.0.0/16 --ip-range=172.20.5.0/24 my-net-limited

常用参数说明:

参数 说明 示例
--driver 指定网络驱动,默认 bridge --driver bridge
--subnet CIDR 格式的子网地址 --subnet=10.10.0.0/16
--gateway 指定网关 IP --gateway=10.10.0.1
--ip-range 限制自动分配的 IP 范围 --ip-range=10.10.1.0/24
--label 为网络添加元数据标签 --label env=prod

4.2.2 管理网络

网络创建后,可以通过以下命令进行管理:

# 列出所有网络
docker network ls

# 查看网络详细信息(包括连接的容器和 IP)
docker network inspect my-net

# 将运行中的容器连接到网络
docker network connect my-net my-container

# 断开容器与网络的连接
docker network disconnect my-net my-container

# 删除网络(需先断开所有容器)
docker network rm my-net
注意: 删除网络前必须确保所有容器已断开连接。如果网络仍有容器连接,docker network rm 会报错。可以使用 docker network disconnect --force 强制断开。

4.3 容器互联与DNS解析

自定义 Bridge 网络最强大的特性是内置的 DNS 解析。当容器加入同一个自定义网络时,Docker 内置的 DNS 服务器会自动将容器名解析为容器的 IP 地址。

4.3.1 通过容器名互联

以下示例演示两个容器在自定义网络中通过容器名通信:

# 1. 创建自定义网络
docker network create app-net

# 2. 启动第一个容器(Web 服务)
docker run -d --name web --network app-net nginx:alpine

# 3. 启动第二个容器(客户端),通过容器名访问 web
docker run --rm --network app-net alpine:latest \
  sh -c "ping -c 3 web"

在客户端容器中,ping web 会自动解析为 web 容器的 IP 地址,无需手动配置 /etc/hosts 或使用 --link。

4.3.2 多网络与别名

一个容器可以同时加入多个网络,实现网络隔离与互联的灵活组合。同时,可以为容器设置网络别名,实现更灵活的服务发现:

# 创建两个网络
docker network create front-net
docker network create back-net

# 启动数据库容器,只加入 back-net
docker run -d --name db --network back-net mysql:8.0

# 启动应用容器,同时加入两个网络,并在 front-net 中设置别名
docker run -d --name app \
  --network front-net \
  --network-alias api-service \
  alpine:latest sleep 3600

# 将 app 容器也连接到 back-net
docker network connect back-net app

# 验证:在 front-net 中可以通过 api-service 访问 app
docker run --rm --network front-net alpine:latest \
  sh -c "ping -c 2 api-service"

4.4 自定义Bridge网络架构图

下图展示了自定义 Bridge 网络的核心架构,包括网络创建、容器加入、DNS 解析和跨网络通信的完整流程:

自定义Bridge网络架构与DNS解析流程 自定义Bridge网络架构与DNS解析流程 Docker Host front-net (172.20.0.0/16) back-net (172.21.0.0/16) web nginx:alpine 172.20.0.2 app api-service (别名) 172.20.0.3 / 172.21.0.2 db mysql:8.0 172.21.0.3 client alpine (临时) ping web 双网络连接 Docker DNS (127.0.0.11) front-net 容器 back-net 容器

4.5 实战:构建微服务网络

以下是一个完整的微服务网络搭建示例,展示如何利用自定义 Bridge 网络实现服务发现和网络隔离:

# 1. 创建业务网络
docker network create --subnet=10.10.0.0/16 --gateway=10.10.0.1 micro-net

# 2. 启动数据库(只对内网暴露)
docker run -d --name mysql-db \
  --network micro-net \
  --network-alias db \
  -e MYSQL_ROOT_PASSWORD=root123 \
  mysql:8.0

# 3. 启动 Redis 缓存
docker run -d --name redis-cache \
  --network micro-net \
  --network-alias redis \
  redis:7-alpine

# 4. 启动后端 API 服务
docker run -d --name api-service \
  --network micro-net \
  --network-alias api \
  -p 8080:8080 \
  my-api:latest

# 5. 启动前端 Nginx(反向代理到 api)
docker run -d --name frontend \
  --network micro-net \
  -p 80:80 \
  nginx:alpine

# 6. 验证 DNS 解析
docker run --rm --network micro-net alpine:latest \
  sh -c "nslookup api && nslookup db && nslookup redis"
关键点: 在这个架构中,api-service 可以通过容器名 db 和 redis 直接访问数据库和缓存,无需硬编码 IP 地址。即使容器重启导致 IP 变化,DNS 会自动更新,应用无需任何配置变更。

4.6 常见故障与排查

在使用自定义 Bridge 网络时,可能会遇到以下问题:

故障现象 可能原因 排查命令 解决方案
容器名无法解析 容器不在同一自定义网络 docker inspect <容器名> | grep Networks 使用 docker network connect 将容器加入同一网络
网络删除失败 仍有容器连接 docker network inspect <网络名> 先断开所有容器,或使用 --force 强制删除
IP 地址冲突 手动指定了已分配的 IP docker network inspect <网络名> | grep IPv4Address 使用 --ip-range 限制自动分配范围,避免手动指定
跨网络通信失败 容器未加入目标网络 docker exec <容器名> ip addr 将容器同时加入多个网络,或使用网络别名
重要提醒: 自定义 Bridge 网络的 DNS 解析仅在同一网络内生效。如果容器 A 和容器 B 不在同一个自定义网络中,即使它们在同一台宿主机上,也无法通过容器名互相访问。这是 Docker 网络隔离的设计原则。