86 lines
3.9 KiB
Markdown
86 lines
3.9 KiB
Markdown
---
|
||
id: devops.docker.compose-network-volume
|
||
title: Compose、网络和数据卷:多服务编排、健康检查、环境变量
|
||
type: lesson
|
||
domain: devops
|
||
stack: [docker]
|
||
tags: [Compose, 网络, 数据卷, 健康检查, 环境变量]
|
||
level: basic
|
||
prerequisites: [devops.docker.image-dockerfile]
|
||
est_hours: 2
|
||
related: [devops.docker.scenario.compose-dev-env, devops.docker.interview]
|
||
week: [3, 6, 13]
|
||
order: 2
|
||
---
|
||
|
||
# Compose、网络和数据卷:多服务编排、健康检查、环境变量
|
||
|
||
## 解释说明
|
||
|
||
- **Compose**:用一个 `compose.yaml` 描述多个服务(应用、数据库、缓存),`docker compose up -d` 一起启动。适合本地开发、测试环境和小规模单机部署;多机、大规模用 Kubernetes。
|
||
- **网络**:Compose 默认为项目创建一个网络,服务之间**用服务名当主机名**访问(`db:5432`),不需要知道 IP。容器内的 `localhost` 指的是容器自己,不是宿主机。
|
||
- **端口映射**:`ports: "8080:8080"` 是“宿主机端口:容器端口”,只有需要从宿主机访问的服务才映射。数据库不映射端口更安全(只在内部网络可见)。
|
||
- **数据卷**:容器删除后可写层的数据就没了。数据库数据要放在**命名卷**(Docker 管理)或**绑定挂载**(宿主机目录,开发时挂源码目录方便热更新)。
|
||
- **健康检查和启动顺序**:`depends_on` 默认只保证“先启动”,不保证“已就绪”。给数据库配 `healthcheck`,应用用 `condition: service_healthy` 等待。应用本身也要有连接重试。
|
||
- **环境变量**:`environment` 直接写,或 `env_file: .env`;`.env` 文件不要提交到 Git。Compose 文件里 `${VAR}` 会从 shell 或项目目录的 `.env` 读取。
|
||
|
||
**常用命令**:`docker compose up -d --build`、`docker compose ps`、`docker compose logs -f api`、`docker compose exec db psql -U app`、`docker compose down`(加 `-v` 会删除数据卷,小心)。
|
||
|
||
## 案例
|
||
|
||
开发 RAG 服务时需要 PostgreSQL(含 pgvector)+ Redis + 应用。用 Compose:新同事 clone 仓库后 `docker compose up -d` 就能跑;数据库数据存在命名卷里,重启不丢;`db` 不映射端口,需要调试时临时 `docker compose exec db psql`。
|
||
|
||
## 代码示例
|
||
|
||
完整文件见 [examples/go-api-compose/compose.yaml](examples/go-api-compose/compose.yaml):
|
||
|
||
```yaml
|
||
services:
|
||
api:
|
||
build: .
|
||
ports:
|
||
- "8080:8080"
|
||
environment:
|
||
DATABASE_URL: postgres://app:app@db:5432/app?sslmode=disable # 用服务名 db 访问
|
||
REDIS_URL: redis://redis:6379/0
|
||
depends_on:
|
||
db:
|
||
condition: service_healthy
|
||
redis:
|
||
condition: service_started
|
||
restart: unless-stopped
|
||
|
||
db:
|
||
image: postgres:17
|
||
environment:
|
||
POSTGRES_USER: app
|
||
POSTGRES_PASSWORD: app
|
||
POSTGRES_DB: app
|
||
volumes:
|
||
- pgdata:/var/lib/postgresql/data
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U app -d app"]
|
||
interval: 5s
|
||
timeout: 3s
|
||
retries: 10
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
|
||
volumes:
|
||
pgdata:
|
||
```
|
||
|
||
## 易错点
|
||
|
||
- **应用里连 `localhost:5432`**:在容器里 localhost 是应用容器自己,要用服务名 `db`。
|
||
- **以为 `depends_on` 会等数据库就绪**:只等容器启动。要配健康检查,应用也要能重试连接。
|
||
- **`docker compose down -v`**:会删掉命名卷,数据库数据全没。
|
||
- **把数据库端口映射到公网服务器的 `0.0.0.0`**:数据库直接暴露在公网。不映射,或者只绑定 `127.0.0.1:5432:5432`。
|
||
- **在 compose 文件里写真实密码并提交**:用 `.env`(加入 `.gitignore`)或部署平台的密钥管理。
|
||
- **镜像版本升级时数据目录变化**:例如 PostgreSQL 新大版本的数据目录约定可能变化,升级前看官方镜像说明并备份。
|
||
|
||
## 面试常问
|
||
|
||
见 [Docker 面试题](interview.md):容器之间怎么通信、数据怎么持久化、depends_on 的局限。
|