22.09-Docker Compose本地环境
要点
- Docker Compose 是本地多服务编排的工具
- 一个典型的 Hono 项目可能需要:API + 数据库 + Redis + 前端
- Compose 用一个 YAML 文件定义所有服务,一条命令启动
- 本地开发环境和生产环境用同一套配置,减少「在我机器上能跑」的问题
内容
1. 为什么需要 Docker Compose
一个完整的后端项目通常不只一个服务:
API 服务 → 需要 PostgreSQL、Redis、可能还有消息队列
前端服务 → 需要 API 地址
数据库 → 需要持久化存储
如果每个服务都手动 docker run,命令会很长而且难以管理:
// terminal
# 启动数据库
docker run -d --name postgres -e POSTGRES_PASSWORD=secret -v pgdata:/var/lib/postgresql/data -p 5432:5432 postgres:16
# 启动 Redis
docker run -d --name redis -p 6379:6379 redis:7
# 启动 API
docker run -d --name api --link postgres --link redis -e DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb -e REDIS_URL=redis://redis:6379 -p 3000:3000 my-api
# 启动前端
docker run -d --name web --link api -e API_URL=http://api:3000 -p 3001:3000 my-webDocker Compose 把这些命令变成一个 YAML 文件。
2. docker-compose.yml
# docker-compose.yml
services:
# API 服务
api:
build:
context: ./apps/api
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb
- REDIS_URL=redis://redis:6379
- NODE_ENV=development
depends_on:
- postgres
- redis
volumes:
- ./apps/api/src:/app/src # 开发期热更新
command: bun run --watch src/index.ts
# 前端服务
web:
build:
context: ./apps/web
dockerfile: Dockerfile
ports:
- "3001:3000"
environment:
- API_URL=http://api:3000
depends_on:
- api
# PostgreSQL 数据库
postgres:
image: postgres:16-alpine
ports:
- "5432:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
# Redis 缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:3. 基本操作
// terminal
# 启动所有服务(后台运行)
docker compose up -d
# 启动所有服务(前台运行,看日志)
docker compose up
# 停止所有服务
docker compose down
# 停止并删除数据卷(清空数据库)
docker compose down -v
# 查看服务状态
docker compose ps
# 查看某个服务的日志
docker compose logs api
docker compose logs -f api # 实时跟踪
# 重新构建镜像
docker compose build
# 只启动某个服务
docker compose up -d api
# 在服务里执行命令
docker compose exec api sh
docker compose exec postgres psql -U postgres -d mydb4. 开发期配置
开发期通常需要热更新和源码挂载:
# docker-compose.dev.yml(覆盖默认配置)
services:
api:
build:
context: ./apps/api
target: builder # 用构建阶段,包含开发依赖
volumes:
- ./apps/api/src:/app/src
- ./apps/api/package.json:/app/package.json
command: bun run --watch src/index.ts
environment:
- NODE_ENV=development
web:
volumes:
- ./apps/web/src:/app/src
command: npm run dev// terminal
# 用开发配置启动
docker compose -f docker-compose.yml -f docker-compose.dev.yml up5. 网络和容器间通信
Compose 会自动创建一个网络,所有服务在同一个网络里,可以用服务名作为主机名互相访问:
services:
api:
environment:
# 直接用服务名 "postgres" 作为主机名
- DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb// apps/api/src/db.ts
// 连接数据库,主机名是 "postgres"
const db = drizzle(postgres(process.env.DATABASE_URL!))6. 数据库初始化
用 init.sql 初始化数据库:
# docker-compose.yml
services:
postgres:
image: postgres:16-alpine
volumes:
- ./dev/init.sql:/docker-entrypoint-initdb.d/init.sql-- dev/init.sql
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
INSERT INTO users (name, email) VALUES ('Admin', '[email protected]');PostgreSQL 会在第一次启动时自动执行 /docker-entrypoint-initdb.d/ 目录下的 SQL 文件。
7. 健康检查
services:
api:
build: .
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5健康检查让 depends_on 可以等待服务真正就绪,而不只是容器启动。
8. 和 K8s 的关系
Docker Compose 适合本地开发和小规模部署。如果需要大规模容器编排(自动扩缩容、滚动更新、跨节点调度),需要用 Kubernetes(K8s)。
| 维度 | Docker Compose | Kubernetes |
|---|---|---|
| 适用规模 | 本地/单机 | 集群 |
| 复杂度 | 低 | 高 |
| 学习曲线 | 几天 | 几周到几个月 |
| 自动扩缩容 | 不支持 | 支持 |
| 服务发现 | DNS | 内置 |
| 负载均衡 | 简单 | 完整 |
对于个人项目和小团队,Docker Compose + 云服务器通常够用。K8s 更适合中大型团队和多服务微服务架构。
9. 小结
Docker Compose 的核心:
- 一个 YAML 文件定义所有服务
docker compose up一条命令启动- 服务间用服务名通信
- 开发期用 volume 挂载源码,实现热更新
- 健康检查确保服务就绪后再启动依赖
Docker Compose 是本地开发环境的标准工具,也是学习容器化和 K8s 的起点。