写在前面
一个应用往往不止一个容器(Web + 数据库 + 缓存 + 反向代理)。docker run 一个个敲很痛苦。Docker Compose 用一个 YAML 文件定义和运行多容器应用——本地开发、测试环境、CI 的利器。
一、什么是 Docker Compose
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| Docker Compose = 多容器编排工具
用一个 docker-compose.yml 描述所有服务
一条命令启动/停止整个应用栈
docker compose up -d # 一键启动所有服务
docker compose down # 一键停止并清理
适合:
✓ 本地开发环境(一键拉起 Web+DB+Redis)
✓ CI/CD 流水线
✓ 测试环境
✓ 单机部署(小型项目)
不适合:
✗ 大规模生产(那是 K8s 的事)
✗ 跨机器部署(单机工具)
|
二、docker-compose.yml 结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| version: "3.8" # compose 文件版本(新版可省略)
services: # 定义所有服务
web:
image: nginx:1.25
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
depends_on:
- app
app:
build: ./myapp # 从 Dockerfile 构建
environment:
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 5s
retries: 5
redis:
image: redis:7
volumes: # 命名卷(持久化)
dbdata:
|
三、核心配置
3.1 服务定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| services:
app:
image: myapp:1.0 # 用现有镜像
build: # 或从 Dockerfile 构建
context: ./app
dockerfile: Dockerfile.prod
args:
VERSION: 1.0 # 构建参数
container_name: myapp # 容器名
restart: unless-stopped # 重启策略
working_dir: /app
user: "1000:1000"
stdin_open: true # -i
tty: true # -t
|
3.2 端口与网络
1
2
3
4
5
6
7
8
9
| ports:
- "8080:80" # 宿主机:容器
- "443:443"
expose:
- "9000" # 只暴露给其他服务(不映射到宿主机)
networks: # 加入自定义网络
- frontend
- backend
|
3.3 数据卷
1
2
3
4
| volumes:
- ./code:/app # 绑定挂载(宿主机目录)
- dbdata:/var/lib/mysql # 命名卷
- /etc/localtime:/etc/localtime:ro # 只读
|
3.4 环境变量
1
2
3
4
5
6
7
| environment:
- DB_HOST=db # 方式1
- DB_PORT=5432
env_file: # 方式2:从文件读
- .env
environment: # 方式3:map
DB_HOST: ${DB_HOST} # 引用宿主机环境变量
|
1
2
3
| # .env 文件(compose 自动读取)
DB_HOST=db
DB_PASSWORD=secret
|
四、服务间依赖
1
2
3
4
5
6
7
| services:
app:
depends_on: # 依赖关系
db:
condition: service_healthy # 等 db 健康检查通过
redis:
condition: service_started # 等 redis 启动即可
|
1
2
3
4
5
6
7
| 注意:
depends_on 只控制「启动顺序」
不等「服务就绪」(除非用 healthcheck + service_healthy)
例:db 容器启动了,但 MySQL 还没接受连接
→ app 连不上 → 应用启动失败
→ 用 healthcheck 让 app 等 db 真正就绪
|
五、网络与服务发现
1
2
3
4
5
6
7
8
9
| services:
web:
networks: [appnet]
db:
networks: [appnet]
networks:
appnet:
driver: bridge
|
1
2
3
4
5
| 同一 Compose 项目、同一网络的容器,可以用「服务名」互相访问:
web 容器里访问 db → 连接 db:5432(不用 IP)
DNS 自动解析服务名
这就是 Compose 内置的服务发现(简单版)
|
六、常用命令
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| # 启动(后台)
docker compose up -d
# 启动并强制重新构建镜像
docker compose up -d --build
# 查看运行状态
docker compose ps
# 查看日志
docker compose logs
docker compose logs -f app # 跟踪某个服务
docker compose logs -f # 跟踪所有
# 停止并删除容器/网络(保留卷)
docker compose down
# 停止并删除卷(彻底清理)
docker compose down -v
# 单独操作某服务
docker compose start app
docker compose stop app
docker compose restart app
# 在运行的服务里执行命令
docker compose exec app bash
# 重新拉镜像后更新
docker compose pull
docker compose up -d
|
七、实战:完整应用栈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| # docker-compose.yml — 一个 .NET + PostgreSQL + Redis + Nginx 栈
version: "3.8"
services:
nginx:
image: nginx:1.25
ports: ["80:80", "443:443"]
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on: [web]
web:
build: ./src
environment:
ConnectionStrings__Db: "Host=db;Database=myapp;Username=postgres;Password=secret"
Redis__Configuration: "redis:6379"
depends_on:
db: { condition: service_healthy }
redis: { condition: service_started }
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- dbdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
dbdata:
|
1
2
3
| # 一键启动整个环境
docker compose up -d
# → Nginx + Web + PostgreSQL + Redis 全部拉起,互相连通
|
八、进阶
8.1 多环境(profiles / override)
1
2
3
4
5
6
7
| # 用 profiles 区分环境
services:
app:
image: myapp
debug-tools:
image: busybox
profiles: ["debug"] # 只在 --profile debug 时启动
|
1
2
| docker compose up -d # 不含 debug-tools
docker compose --profile debug up -d # 含 debug-tools
|
1
2
3
4
| # override 文件(docker-compose.override.yml 自动叠加)
# docker-compose.yml(基础)
# docker-compose.override.yml(本地覆盖:加调试端口、挂源码)
# docker compose up 自动合并
|
8.2 资源限制
1
2
3
4
5
6
7
8
9
| services:
app:
deploy:
resources:
limits:
cpus: "1.0"
memory: 512M
reservations:
memory: 256M
|
九、小结
- Compose:一个 YAML 定义多容器,一条命令管理
- 适合:本地开发、CI、测试、单机小型生产
- 核心:services(服务)/ volumes(持久化)/ networks(网络)
- 服务发现:同网络容器用服务名互访(DNS)
- 依赖:depends_on + healthcheck 控制启动与就绪顺序
- 命令:up/down/logs/exec/ps
下一篇讲 Docker 网络与存储——容器的隔离与持久化细节。