好的,用一个具体的示例来展示区别:

📁 项目结构

myapp/
├── docker-compose.yml
├── frontend/
└── backend/

🐳 docker-compose.yml

version: '3.8'

services:
  frontend:
    image: nginx
    ports: ["80:80"]
    # 使用自定义网络

  backend:
    image: node:18
    # 使用自定义网络
  
  database:
    image: postgres:15
    # 使用自定义网络

# 自定义网络
networks:
  myapp-network:
    driver: bridge

🔧 两种配置对比

方案1:不加自定义网络

# 所有服务使用默认网络
services:
  frontend: 
    # ...
  backend:
    # ...
  database:
    # ...
# 不定义networks section

方案2:加入自定义网络

services:
  frontend:
    networks: ["myapp-network"]
  backend:
    networks: ["myapp-network"] 
  database:
    networks: ["myapp-network"]

networks:
  myapp-network:
    driver: bridge

🌐 通信方式对比

不加自定义网络时:

# 在backend容器内:
ping frontend          # ❌ 失败
ping backend           # ❌ 失败  
ping database          # ❌ 失败

# 只能用容器IP访问,但IP会变化

加入自定义网络后:

# 在backend容器内:
ping frontend          # ✅ 成功
ping backend           # ✅ 成功
ping database          # ✅ 成功

# 还可以用服务名访问:
curl http://frontend    # ✅ 访问前端
psql -h database        # ✅ 连接数据库

🚀 实际代码中的好处

backend 应用配置:

// 连接数据库 - 直接用服务名
const dbConfig = {
  host: 'database',     // ✅ 而不是 '172.20.0.5'
  port: 5432,
  user: 'admin'
};

// 调用前端服务
const frontendUrl = 'http://frontend'; // ✅ 而不是 IP 地址

💡 核心优势总结

场景不加自定义网络加自定义网络
服务间通信❌ 只能用IP✅ 可用服务名
项目隔离❌ 所有项目混在一起✅ 项目间网络隔离
DNS解析❌ 只能解析容器名✅ 可解析服务名和容器名

结论:自定义网络让容器可以通过服务名直接通信,简化配置并提高可维护性。

更多推荐