搞懂"冒号左右"到底看哪个 · 一篇讲透两种网络场景
Docker Compose 里的端口映射格式永远是:
宿主机端口 : 容器端口 左边 右边
一个口诀:左边是"门牌号",右边是"房间号"。外部世界按门牌号找你,房间内部互相串门用的是房间号。
外部访问(浏览器、IDEA、其他机器)
│
▼
┌──────────────────────────┐
│ 宿主机 Windows │
│ localhost:3306 ◀── 左边端口(门牌号)
│ │ 映射 │
│ ┌─────┴──────────────┐ │
│ │ 容器 mysql │ │
│ │ 内部监听 3306 │ ◀── 右边端口(房间号)
│ └────────────────────┘ │
└──────────────────────────┘
看冒号左边(宿主机端口)。因为你的应用在 IDEA 里跑、在 Windows 宿主机上跑,它只能触达暴露在宿主机上的那个端口。
| 你要连的服务 | 用什么端口 | 连接串示例 |
|---|---|---|
| MySQL | 3306 | jdbc:mysql://localhost:3306/app_db |
| Redis | 6379 | redis://localhost:6379 |
| MongoDB | 27017 | mongodb://root:root123@localhost:27017 |
| RabbitMQ(AMQP) | 5672 | amqp://localhost:5672 |
| RabbitMQ(管理界面) | 15672 | http://localhost:15672 |
| RocketMQ NameServer | 9876 | namesrv=localhost:9876 |
| RocketMQ Dashboard | 8180 | http://localhost:8180 |
localhost// ✅ 你日常用的方式 jdbc:mysql://localhost:3306/app_db
// 容器之间互相调用 jdbc:mysql://mysql:3306/app_db
为什么场景 B 不能用 localhost?因为容器里的 localhost 指的是容器自己,不是宿主机。它在自己的小房间里喊"localhost",没人应答。
假设把 compose 改成 9999:3306,同一个是 mysql 容器,两种访问方式的表现完全不同:
| 访问方 | 原来 | 改映射后 | 受影响吗 |
|---|---|---|---|
| 本地 IDEA(宿主机) | localhost:3306 | localhost:9999 | 必须改 |
| 另一个容器(app) | mysql:3306 | mysql:3306 | 完全不变 |
因为目前你的工作流是 "中间件用 Docker,应用本地 IDEA 跑"——这是开发期最舒服的方式。你的应用根本不在容器里,所以永远只用 localhost:左边端口 这一招,自然碰不到容器互调。
容器互调通常出现在这些场合:
services:
mysql:
image: mysql:8.0
...
app: # ← 你的应用也成了容器
image: my-app:latest
depends_on: [mysql]
environment:
# host 是服务名 mysql,端口是容器内 3306(右边)
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/app_db
# ↑↑↑ 注意:不是 localhost,不是宿主机端口