This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
all-in-kingsoft/gyh/docker/docker-compose使用指南.md
T

897 lines
18 KiB
Markdown
Raw 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.
# Docker Compose 使用指南
> Docker Compose 用 **YAML 文件**定义多容器应用,一条 `docker compose up` 启动所有服务。**开发环境和生产环境都大量使用。**
---
## 快速开始(TL;DR)
```bash
# 1. 创建 docker-compose.yml
# 2. 启动所有服务
docker compose up -d
# 3. 查看状态
docker compose ps
# 4. 查看日志
docker compose logs -f
# 5. 停止并清理
docker compose down
```
**目录:** [基本结构](#一基本结构) · [完整示例](#二完整示例) · [常用配置](#三常用配置详解) · [多环境](#四多环境配置) · [常用命令](#五常用命令) · [常见问题](#六常见问题) · [模板速查](#七常用模板速查) · [格式演进](#八compose-文件格式演进) · [高级配置](#九高级配置) · [最佳实践](#十最佳实践) · [速查卡](#十一快速参考卡)
---
## 一、基本结构
```yaml
# docker-compose.yml
version: '3.8'
services:
web: # 前端/后端应用
db: # 数据库
redis: # 缓存
nginx: # 反向代理
networks: # 网络定义
volumes: # 数据卷定义
```
---
## 二、完整示例
### 2.1 Node.js + MySQL + Redis 全栈项目
```yaml
version: '3.8'
services:
# ========== 后端应用 ==========
api:
build:
context: ./server
dockerfile: Dockerfile
args:
NODE_ENV: production
container_name: my-api
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=3306
- DB_USER=root
- DB_PASSWORD=root123
- DB_NAME=mydb
- REDIS_HOST=redis
- REDIS_PORT=6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: always
networks:
- app-network
volumes:
- api-logs:/app/logs
# ========== 前端应用 ==========
web:
build:
context: ./client
dockerfile: Dockerfile
container_name: my-web
ports:
- "80:3000"
depends_on:
- api
restart: always
networks:
- app-network
# ========== 数据库 ==========
db:
image: mysql:8.0
container_name: my-db
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: mydb
MYSQL_USER: admin
MYSQL_PASSWORD: admin123
ports:
- "3306:3306"
volumes:
- db-data:/var/lib/mysql
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
restart: always
networks:
- app-network
# ========== 缓存 ==========
redis:
image: redis:7-alpine
container_name: my-redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --appendonly yes
restart: always
networks:
- app-network
# ========== 反向代理 ==========
nginx:
image: nginx:alpine
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- web
- api
restart: always
networks:
- app-network
# ========== 网络 ==========
networks:
app-network:
driver: bridge
# ========== 数据卷 ==========
volumes:
db-data:
redis-data:
api-logs:
```
---
## 三、常用配置详解
### 3.1 `build` — 从 Dockerfile 构建
```yaml
services:
# 方式一:当前目录(自动找 Dockerfile)
web:
build: .
# 方式二:指定上下文和 Dockerfile
web:
build:
context: ./frontend
dockerfile: Dockerfile.prod
# 方式三:加构建参数
web:
build:
context: .
dockerfile: Dockerfile
args:
NODE_ENV: production
VERSION: 1.0.0
target: production # 多阶段构建指定阶段
# 方式四:直接用已有镜像(不构建)
db:
image: mysql:8.0
```
### 3.2 `depends_on` — 启动顺序
```yaml
services:
api:
depends_on:
db:
condition: service_healthy # 等 db 健康检查通过
redis:
condition: service_started # 等 redis 启动即可
```
> **注意:** `depends_on` 只管**启动顺序**,不管**可用性**。`condition: service_healthy` + `healthcheck` 才能真正等服务就绪。
### 3.3 `healthcheck` — 健康检查
```yaml
services:
db:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s # 每 10 秒检查一次
timeout: 5s # 超时时间
retries: 5 # 最多重试 5 次
start_period: 30s # 容器启动后等 30 秒才开始检查(给数据库初始化时间)
```
**常见健康检查命令:**
| 服务 | 健康检查命令 |
|------|-------------|
| MySQL | `mysqladmin ping -h localhost` |
| Redis | `redis-cli ping` |
| Node.js | `wget -qO- http://localhost:3000/health || exit 1` |
| Nginx | `curl -f http://localhost/ || exit 1` |
| PostgreSQL | `pg_isready -h localhost` |
### 3.4 `environment` — 环境变量
```yaml
# 方式一:列表格式
environment:
- NODE_ENV=production
- DB_HOST=db
# 方式二:字典格式(推荐,更易读)
environment:
NODE_ENV: production
DB_HOST: db
DB_PORT: 3306
# 方式三:从 .env 文件加载(最推荐)
env_file:
- .env.production
# 混合使用
environment:
NODE_ENV: production
DB_HOST: db
env_file:
- .env
```
### 3.5 `volumes` — 数据持久化
```yaml
volumes:
# 命名卷(推荐,Docker 管理)
volumes:
- db-data:/var/lib/mysql
# 绑定挂载(绑定到宿主机路径)
volumes:
- ./data:/app/data
# 只读挂载
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
# 匿名卷(不需要命名)
volumes:
- /tmp/data
```
### 3.6 `restart` — 重启策略
```yaml
restart: always # 永远重启(包括手动停止后重启)
restart: on-failure # 仅失败时重启
restart: unless-stopped # 除非手动停止,否则重启(推荐)
restart: no # 不自动重启(默认)
```
### 3.7 `ports` vs `expose`
```yaml
ports:
- "8080:80" # 宿主端口:容器端口(外部可访问)
- "127.0.0.1:8080:80" # 仅本地可访问
- "3000" # 随机端口
expose:
- "3000" # 仅容器间通信,外部不可访问
```
---
## 四、多环境配置
### 4.1 使用覆盖文件
```yaml
# docker-compose.yml(基础配置)
services:
api:
build: .
environment:
- NODE_ENV=development
volumes:
- ./server:/app # 开发时热重载
db:
image: mysql:8.0
```
```yaml
# docker-compose.prod.yml(生产覆盖)
services:
api:
environment:
- NODE_ENV=production
# 覆盖开发时的 volume 挂载
volumes: [] # 生产时不要挂载宿主机目录
```
```bash
# 使用:基础 + 生产覆盖
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```
### 4.2 更简洁的方式(环境变量控制)
```yaml
# docker-compose.yml
services:
api:
build: .
environment:
- NODE_ENV=${NODE_ENV:-development}
- DB_HOST=${DB_HOST:-db}
volumes:
- ${MOUNT_VOLUMES:-./server:/app}
```
```bash
# 开发环境(默认)
docker compose up -d
# 生产环境
NODE_ENV=production MOUNT_VOLUMES="" docker compose up -d
```
---
## 五、常用命令
```bash
# 启动所有服务(后台)
docker compose up -d
# 启动所有服务(前台,看日志)
docker compose up
# 启动单个服务
docker compose up -d db redis
# 停止所有服务(不删除容器和数据卷)
docker compose stop
# 停止并删除所有容器
docker compose down
# 停止并删除容器、网络
docker compose down --rmi all
# 重建镜像并启动(代码改动后)
docker compose up -d --build
# 重建并重新初始化数据卷
docker compose down -v
docker compose up -d --build
# 查看服务状态
docker compose ps
# 查看服务日志
docker compose logs
docker compose logs -f api # 只看 api 服务的日志
docker compose logs -f --tail 100 db # 只看 db 的最后 100 行
# 进入运行中的容器
docker compose exec api bash
docker compose exec db mysql -u root -p
# 执行单次命令
docker compose run api npm run db:migrate
docker compose run --rm web npm test # --rm 执行完自动删除
# 查看资源占用
docker compose ps
# 构建并启动
docker compose build
docker compose up -d
# 更新镜像
docker compose pull
docker compose up -d --pull always
```
---
## 六、常见问题
### 6.1 容器间无法互相访问
```yaml
# 确保所有服务在同一网络下
services:
api:
networks: [app-network]
db:
networks: [app-network]
networks:
app-network:
driver: bridge
```
> 默认情况下,Docker Compose 会为同一个 compose 文件创建同一个网络,不同 compose 文件的容器**不能互相访问**。
### 6.2 数据库启动慢,应用连不上
```yaml
services:
api:
depends_on:
db:
condition: service_healthy # 健康检查通过才启动
```
或在应用代码中添加重试逻辑。
### 6.3 端口冲突
```bash
# 查看端口占用
netstat -ano | findstr :3000 # Windows
lsof -i :3000 # macOS/Linux
```
修改 `docker-compose.yml` 中的端口映射:
```yaml
ports:
- "3001:3000" # 宿主机 3001 → 容器 3000
```
### 6.4 `.env` 文件
```bash
# 在项目根目录创建 .env 文件
DB_HOST=db
DB_PASSWORD=root123
NODE_ENV=production
COMPOSE_PROJECT_NAME=myapp
```
> Docker Compose 会**自动读取**当前目录的 `.env` 文件,无需额外配置。`$DB_HOST` 在 `docker-compose.yml` 中会被自动替换。
---
## 七、常用模板速查
### 7.1 纯前端静态站点(Nginx)
```yaml
services:
web:
build: .
ports:
- "80:80"
restart: always
```
### 7.2 Node.js + PostgreSQL
```yaml
services:
app:
build: .
ports: ["3000:3000"]
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
networks:
volumes:
pg-data:
```
### 7.3 Next.js 全功能模板
```yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
target: production
ports: ["3000:3000"]
environment:
- NODE_ENV=production
- DATABASE_URL=$DATABASE_URL
- NEXTAUTH_SECRET=$NEXTAUTH_SECRET
restart: always
networks: [app-network]
db:
image: postgres:16-alpine
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=app
- POSTGRES_PASSWORD=$DB_PASSWORD
volumes: [pg-data:/var/lib/postgresql/data]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
networks: [app-network]
redis:
image: redis:7-alpine
volumes: [redis-data:/data]
networks: [app-network]
networks:
app-network:
volumes:
pg-data:
redis-data:
```
---
## 八、Compose 文件格式演进
### 8.1 新版 Compose Specification(推荐)
**不再需要 `version` 字段**,Docker Compose V2 起默认使用 Compose Specification 格式:
```yaml
# 新版写法(推荐)
services:
app:
image: node:20-alpine
ports:
- "3000:3000"
environment:
NODE_ENV: production
networks:
default:
driver: bridge
volumes:
data:
```
> **关键区别:**
> - V3 及以下:必须写 `version: '3.8'`,字段名用点号分隔(如 `networks.default`)
> - V4 及以上(Compose Specification):**不需要 version**,字段名用嵌套格式(如 `networks:` 下的 `default:`)
### 8.2 如何判断使用哪种格式
```bash
# 查看 Compose 版本
docker compose version
# Compose V2+(2020 年起)→ 使用 Compose Specification 格式
# 使用 `docker compose`(注意是空格,不是连字符)
```
> **建议:** 新项目直接使用无 version 的新格式,兼容性更好。
---
## 九、高级配置
### 9.1 `deploy` — 资源限制(适用于 Compose V3+)
```yaml
services:
api:
image: my-api:latest
deploy:
replicas: 3 # 副本数(Swarm 模式)
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
update_config:
parallelism: 1 # 每次更新 1 个容器
delay: 10s
order: start-first # 先启动新再停止旧
rollback_config:
parallelism: 1
delay: 5s
resources:
limits:
cpus: '0.5' # 最多 0.5 核 CPU
memory: 512M # 最多 512MB 内存
reservations:
cpus: '0.25'
memory: 128M
```
> **注意:** `deploy` 在 `docker compose up`(非 Swarm 模式)下**部分字段不生效**(`replicas`、`update_config` 等)。资源限制 `limits/reservations` 在普通模式下仍然生效。
### 9.2 `profiles` — 按需启停服务
```yaml
services:
web:
image: nginx:alpine
profiles: ["app"]
db:
image: postgres:16-alpine
profiles: ["db", "app"]
redis:
image: redis:7-alpine
profiles: ["cache", "app"]
monitoring:
image: grafana/grafana
profiles: ["monitoring"]
```
```bash
# 启动 app 相关服务(web + db + redis)
docker compose --profile app up -d
# 启动 app + 监控
docker compose --profile app --profile monitoring up -d
# 启动所有带 profile 的服务
docker compose --profile app --profile db --profile cache --profile monitoring up -d
# 启动所有服务(包括无 profile 的)
docker compose up -d
# 查看当前 profile 配置
docker compose config --profiles
```
> **场景:** 开发时只启动 `app`,测试时加上 `db`,生产环境加上 `monitoring`。
### 9.3 `configs` — 配置文件管理
```yaml
services:
nginx:
image: nginx:alpine
configs:
- source: nginx_conf
target: /etc/nginx/conf.d/default.conf
mode: 0444 # 文件权限
app:
image: my-app:latest
configs:
- source: app_config
target: /etc/app/config.yaml
mode: 0440
configs:
nginx_conf:
file: ./configs/nginx.conf
app_config:
file: ./configs/app.yaml
external: false # 本地文件
```
> **适用场景:** 需要分发配置文件但不想硬编码到镜像中。
### 9.4 `secrets` — 敏感信息管理
```yaml
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_pass
secrets:
- db_root_pass
- db_config
secrets:
db_root_pass:
file: ./secrets/db_root_pass.txt # 从文件读取
db_config:
string: '{"max_connections": 100}' # 直接写字符串
```
> **安全建议:** 敏感信息不要写死在 `docker-compose.yml` 中,使用 `secrets` 或 `.env` 文件管理。
### 9.5 其他实用配置
```yaml
services:
app:
image: node:20-alpine
# 指定运行用户
user: "1000:1000"
# 工作目录
working_dir: /app
# 覆盖默认入口点和命令
entrypoint: ["node"]
command: ["server.js"]
# 容器别名(同一 compose 内通过别名访问)
container_name: my-app
# 标签(元数据)
labels:
- "com.example.description=API Server"
- "com.example.environment=production"
# 时区
environment:
- TZ=Asia/Shanghai
# 挂载共享内存(深度学习场景)
shm_size: '2gb'
# 安全选项
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
# 资源限制
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
```
---
## 十、最佳实践
### 10.1 安全性
```yaml
# ✅ 使用非 root 用户
user: "1000:1000"
# ✅ 最小化权限
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
# ✅ 敏感信息用 secrets 或 .env
secrets:
- db_password
# ❌ 避免使用 privileged
# privileged: true
# ❌ 避免绑定 0.0.0.0
# ports:
# - "0.0.0.0:3000:3000"
```
### 10.2 可靠性
```yaml
# ✅ 所有外部依赖都加 healthcheck
db:
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
start_period: 30s
# ✅ 合理的重启策略
restart: unless-stopped
# ✅ 依赖顺序用 condition
depends_on:
db:
condition: service_healthy
```
### 10.3 可维护性
```yaml
# ✅ 使用 .env 管理变量
# .env
COMPOSE_PROJECT_NAME=myapp
MYSQL_ROOT_PASSWORD=xxxxx
NODE_ENV=production
# docker-compose.yml
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- db-data:/var/lib/mysql
# ✅ 命名卷而不是绑定挂载(数据持久化)
volumes:
db-data: # Docker 管理,更安全
# ✅ 用 profiles 组织服务
# 开发只启动 app + db
# docker compose --profile dev up -d
```
### 10.4 性能优化
```yaml
# ✅ 生产环境使用 Alpine 镜像
image: node:20-alpine # 约 150MB
# vs
image: node:20 # 约 1GB
# ✅ 限制资源使用
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# ✅ 只暴露必要的端口
# ❌ 数据库不要暴露到宿主机
# db:
# ports:
# - "3306:3306" # 删除这行
# ✅ 使用 expose 代替 ports(容器间通信)
db:
expose:
- "3306"
```
---
## 十一、快速参考卡
| 字段 | 用途 | 示例 |
|------|------|------|
| `image` | 使用已有镜像 | `image: nginx:alpine` |
| `build` | 从 Dockerfile 构建 | `build: ./app` |
| `ports` | 端口映射(外部可访问) | `"80:80"` |
| `expose` | 端口暴露(仅容器间) | `"3000"` |
| `volumes` | 数据持久化 | `data:/var/lib/mysql` |
| `environment` | 环境变量 | `NODE_ENV: production` |
| `depends_on` | 启动依赖 | `db: condition: service_healthy` |
| `healthcheck` | 健康检查 | `test: ["CMD", "curl", ...]` |
| `restart` | 重启策略 | `unless-stopped` |
| `networks` | 网络归属 | `app-network` |
| `profiles` | 按需启停 | `["dev", "monitoring"]` |
| `secrets` | 敏感信息管理 | `file: ./secrets/xxx` |
| `configs` | 配置文件管理 | `target: /etc/app/config` |
| `deploy.resources` | 资源限制 | `cpus: '0.5', memory: 512M` |
| `container_name` | 固定容器名 | `my-container` |
| `user` | 运行用户 | `"1000:1000"` |