Vibe Tutorial
云服务器运维与项目部署

13.6 Docker容器网络

Tip

由于容器是隔离的(像一个个独立的小房间),默认情况下它们之间是听不到对方说话的。你需要给它们拉电话线,这就是Docker Network


1. 为什么要学这个?

你的 Node.js 应用要连 MySQL。 你在代码里写 localhost:3306。 报错 Connection Refused

因为 localhost 在容器里指的是容器自己,而不是宿主机,也不是另一个容器。 不懂 Docker Network,你的微服务就是一座座孤岛。


2. 核心概念:Docker Compose

虽然可以用 docker network create 手动配网,但太麻烦。 我们通常使用 Docker Compose 来编排多个容器。它会自动创建一个局域网,让容器可以通过服务名互相访问。

2.1 DNS Magic

在 Docker Compose 网络里:

  • Service Name (db) 会自动解析成 MySQL 容器的 IP。
  • 在 Node.js 代码里,配置 host: 'db' 就能连上。

3. 解决方案 (HOW)

3.1 编写 docker-compose.yml

在项目根目录:

version: '3'

services:
  # 服务 1: Web 应用
  web:
    build: .
    ports:
      - "3000:3000"
    environment:
      # 注意这里 host 写的是 db,不是 localhost
      - DATABASE_URL=mysql://user:pass@db:3306/mydb
    depends_on:
      - db

  # 服务 2: 数据库
  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=pass
      - MYSQL_DATABASE=mydb
    volumes:
      - ./data:/var/lib/mysql # 数据持久化

3.2 运行

# 一键启动所有服务
docker-compose up -d

# 查看状态
docker-compose ps

3.3 网络拓扑图

graph TD
    User["外部用户"] -->|"Step 1: port 3000"| WebContainer["Web 容器"]
    
    subgraph DockerNet ["Docker Network (内部局域网)"]
        WebContainer -->|"Step 2: host='db'"| DBContainer["MySQL 容器"]
    end
    
    WebContainer --x|"Step 3: localhost 不通"| DBContainer
    
    style WebContainer fill:#e1bee7,stroke:#8e24aa
    style DBContainer fill:#c8e6c9,stroke:#2e7d32

4. 避坑指南

❌ 不要这样做 ✅ 应该这样做 为什么
使用 IP 地址 使用 Service Name 容器重启后内部 IP (172.x.x.x) 可能会变,但 Service Name (db) 永远不变。
依赖启动顺序 实现重试机制 depends_on 只管启动顺序,不管数据库是否 Ready。代码里最好加重试逻辑 (wait-for-it)。
Localhost 理解 Localhost 99% 的新手坑:在容器里用 localhost 连别的服务。Localhost inside container = Container itself。

5. 真实案例

Story

2019年,死板的 IP

某开发者查到 Docker 分配给数据库的 IP 是 172.18.0.2。 于是他在代码里写死了这个 IP。 两个月后,服务器重启,Docker 容器启动顺序变了,Redis 先启动拿到了 172.18.0.2,数据库变成了 172.18.0.3。 本来应该写进数据库的交易记录,全被写到了 Redis 里(或者直接连接失败)。

Vibe 心法:在容器的宇宙里,IP 是流动的沙尘。永远不要在代码里固化具体的容器 IP,而要利用 Docker Compose 的 DNS 服务名发现机制。信任服务名,就是信任系统解耦的未来。


6. 本章小结

  1. Compose: 是管理多容器应用的最佳实践。
  2. Service Name: 是容器间的通关密语。
  3. Localhost: 在容器世界里,它最孤独。