10.3.2 服务之间如何对话——网络与卷:服务间通信与数据共享
容器间通信,用服务名就行。
Docker Compose 网络原理
Docker Compose 会自动为项目创建一个专属网络,所有服务都加入这个网络。在这个网络中,服务可以通过服务名相互访问。
服务间通信
使用服务名作为主机名
yaml
services:
api:
environment:
# 使用服务名 postgres 而非 localhost
- DATABASE_URL=postgresql://user:pass@postgres:5432/mydb
# 使用服务名 redis
- REDIS_URL=redis://redis:6379常见错误
在容器内使用 localhost 是访问容器自己,而非其他服务。必须使用服务名!
端口规则
| 场景 | 配置 | 说明 |
|---|---|---|
| 容器间通信 | 直接使用容器端口 | postgres:5432 |
| 外部访问 | 需要端口映射 | ports: "5432:5432" |
| 仅内部访问 | 使用 expose | expose: ["5432"] |
yaml
services:
postgres:
image: postgres:15
# 不映射端口,外部无法直接访问,更安全
expose:
- "5432"自定义网络
多网络隔离
yaml
services:
frontend:
networks:
- frontend-network
api:
networks:
- frontend-network
- backend-network
postgres:
networks:
- backend-network # 数据库不暴露给前端
networks:
frontend-network:
backend-network:网络别名
yaml
services:
postgres:
networks:
default:
aliases:
- db
- database现在可以用 postgres、db、database 三个名称访问同一服务。
数据卷详解
卷的类型
| 类型 | 语法 | 特点 |
|---|---|---|
| 命名卷 | volume-name:/path | Docker 管理,持久化 |
| 绑定挂载 | ./host/path:/container/path | 直接映射主机目录 |
| 匿名卷 | /path | 临时,容器删除即丢失 |
命名卷(推荐用于数据持久化)
yaml
services:
postgres:
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data: # 声明命名卷
driver: local绑定挂载(开发时常用)
yaml
services:
api:
volumes:
# 将本地代码挂载到容器,实现热重载
- ./api:/app
# 排除 node_modules(使用匿名卷)
- /app/node_modules只读挂载
yaml
services:
nginx:
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro数据共享场景
场景一:多服务共享数据
yaml
services:
api:
volumes:
- shared-uploads:/app/uploads
worker:
volumes:
- shared-uploads:/app/uploads
volumes:
shared-uploads:场景二:初始化脚本
yaml
services:
postgres:
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:roPostgreSQL 会在首次启动时自动执行 /docker-entrypoint-initdb.d/ 下的脚本。
查看网络和卷
bash
# 查看项目网络
docker network ls | grep myproject
# 查看网络详情
docker network inspect myproject_default
# 查看卷
docker volume ls
# 查看卷详情
docker volume inspect myproject_postgres-data清理资源
bash
# 停止并删除容器,但保留卷
docker compose down
# 停止并删除容器和卷(危险!数据会丢失)
docker compose down -v
# 删除未使用的卷
docker volume prune数据安全
docker compose down -v 会删除所有数据卷,生产环境慎用!
最佳实践
- 生产环境不映射数据库端口:避免外部直接访问
- 使用命名卷持久化数据:比绑定挂载更可靠
- 敏感服务使用独立网络:隔离前后端
- 定期备份数据卷:使用
docker run挂载卷并执行备份
