Files
zhuangang/topics/devops/docker/02-compose-network-volume.md

86 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 的局限。