什么是 Docker Compose 的网络(network),为什么你需要它,它是怎么工作的
Docker Compose 的网络就是:让多个容器之间能像“连上同一个局域网”一样互相通信,不用管 IP,用服务名就能访问彼此。
就像家里连接到同一个 WiFi 的手机、电脑、电视,它们都能互相发现对方,Docker 里的容器也是一样 —— 靠网络联通。
🚀 举个通俗的例子
你用 Docker Compose 启动两个服务:
services:backend:build: .db:image: postgres
这两个服务就会自动被 Docker Compose 放在同一个虚拟网络里,比如叫 myproject_default
。
于是:
backend
容器可以通过db:5432
访问数据库(注意:用的是服务名db
,不是 IP)db
容器也可以访问backend
,只要知道它叫backend
就像是:
后端程序:嘿!我要连接数据库,主机叫 db,端口 5432。
数据库容器:我在这儿!同一个网里能找到我。
你不用写 127.0.0.1
或 IP 地址,而是用 db
这个名字就能通信,Docker 自动给你 DNS 做了绑定。
🔧 技术细节
Docker Compose 在启动时:
- 会创建一个默认网络(通常叫
项目名_default
) - 把每个服务都加入这个网络
- 容器之间能用「服务名」来相互访问(Docker 内置 DNS)
比如:
ping db
在 backend
容器里可以 ping 通 db
✅ 网络的作用总结
功能 | 举例 |
---|---|
容器之间互通 | backend 可以访问 db ,不需要知道 IP,只用服务名 |
DNS 自动解析 | 用服务名 db 自动解析成容器 IP |
隔离性 | 默认网络只让你定义的服务互通,外面进不来 |
多网络支持 | 你可以把某些容器放进多个网络,实现访问控制 |
🔥 真实项目常见用法
services:backend:build: .depends_on: [db]db:image: postgres
你可以在后端的代码里这么写连接数据库的代码:
psycopg2.connect(host="db", # 注意:不是 localhost,是服务名port=5432,user="postgres",password="xxx"
)
这就是网络在背后帮你搞定连接。
✅ 如果你不设置网络,Docker 会帮你自动建一个默认网络
但你也可以手动定义网络规则:
networks:mynetwork:services:backend:networks:- mynetworkdb:networks:- mynetwork
🧠 总结:Docker Compose 网络,说人话就是
你想干啥 | 网络怎么帮你实现 |
---|---|
让多个容器互相通信 | 自动分配同一个网络 |
不用关心 IP 地址 | 用服务名访问彼此 |
控制谁能访问谁 | 配置多个网络实现隔离 |
那 “多个网络” + “访问控制”。 它又是什么意思呢。
✅ 一句话通俗解释:
Docker 允许你把一个容器放进 多个网络,这样你就能控制它能访问谁、谁能访问它,而不是所有容器都能随便通信。
这就像现实生活中的网络安全策略:
- 你可以让你的手机连上 WiFi,也连上蓝牙
- 手机可以通过 WiFi访问互联网,通过蓝牙访问耳机
- 但耳机不能上网,因为它只连了蓝牙
同理:一个 Docker 容器可以“同时加入两个不同的局域网”,从而访问不同的服务,但不是所有容器都能互相看见对方。
🧠 举个具体的例子:
你有三个服务:
services:backend:build: ./backendnetworks:- appnet- dbnetfrontend:build: ./frontendnetworks:- appnetdb:image: postgresnetworks:- dbnet
定义的两个网络:
networks:appnet: # 前端和后端都在这个网里dbnet: # 后端和数据库在这个网里
✅ 它们之间的关系图如下:
[frontend] -- appnet --> [backend] -- dbnet --> [db]
frontend
和backend
在同一个网络appnet
,可以互相访问backend
和db
在同一个网络dbnet
,也可以互相访问- 但
frontend
和db
不在同一个网络里,所以不能互相访问!
🧩 为什么这很有用?
这就是访问控制的体现:
- 你不希望前端直接连数据库(安全问题)
- 你只希望前端通过后端间接访问数据库
- 所以你用网络隔离来“物理封锁”
这种结构在真实项目中非常常见,被称为「服务分层、最小暴露原则」。
🧪 验证方法
你可以进容器里试试:
# 进入 frontend 容器:
docker exec -it frontend bash# 试图 ping db,会失败
ping db
# → ping: unknown host# 进入 backend 容器:
docker exec -it backend bash# ping frontend 和 ping db 都能成功
ping frontend
ping db
✅ 总结(一句话说人话)
把容器放进多个网络,就像让它拥有“多个朋友圈”。谁能看见谁、谁能说话,全靠你设置它在哪些“群”里。