第 212 章:Docker Compose 多容器编排
学习目标
- 掌握 docker-compose.yml 语法
- 实现多容器应用编排
- 学会依赖管理 / 网络 / 卷
- 实现本地开发环境
一、Docker Compose 简介
Compose 是用于多容器应用编排的工具,用一份 YAML 配置定义全部服务。
二、安装
bash
# Docker Desktop 自带
# Linux:
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证
docker compose version三、核心概念
yaml
# docker-compose.yml
version: '3.8' # 版本
services: # 服务(容器)
app:
build: . # 或 image:
ports:
- "3000:3000"
environment:
- DB_HOST=db
volumes:
- .:/app
depends_on:
- db
volumes: # 数据卷
dbdata:
networks: # 网络
mynet:四、完整示例
4.1 Node + MySQL + Redis
yaml
version: '3.8'
services:
app:
build: .
image: myapp:1.0
container_name: myapp
restart: unless-stopped
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_PORT=3306
- DB_USER=admin
- DB_PASS=${DB_PASS}
- REDIS_HOST=cache
- REDIS_PORT=6379
volumes:
- ./uploads:/app/uploads
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
networks:
- app-net
db:
image: mysql:8
container_name: mydb
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASS}
MYSQL_DATABASE: myapp
volumes:
- dbdata:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3306:3306"
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-net
cache:
image: redis:7-alpine
container_name: myredis
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redisdata:/data
networks:
- app-net
nginx:
image: nginx:alpine
container_name: mynginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certs:/etc/nginx/certs
depends_on:
- app
networks:
- app-net
volumes:
dbdata:
redisdata:
networks:
app-net:
driver: bridge.env:
env
DB_PASS=secret1234.2 启动
bash
docker compose up -d # 后台启动
docker compose ps # 状态
docker compose logs -f app # 日志
docker compose logs --tail 100 app
docker compose stop # 停止
docker compose down # 停止并删除容器
docker compose down -v # 删除卷五、常用命令
5.1 服务管理
bash
# 启动
docker compose up -d [service]
docker compose start service
# 停止
docker compose stop
docker compose stop service
# 重启
docker compose restart service
# 重新构建
docker compose build
docker compose build --no-cache
# 删除
docker compose down
docker compose rm service # 删除停止的容器5.2 查看
bash
docker compose ps # 容器状态
docker compose top # 进程
docker compose images # 镜像
docker compose logs # 日志
docker compose port app 3000 # 端口映射5.3 执行
bash
# 在运行容器里执行
docker compose exec app bash
docker compose exec db mysql -uroot -p
# 一次性运行
docker compose run --rm app node script.js5.4 扩缩容
bash
docker compose up -d --scale app=3六、Compose 文件详解
6.1 build
yaml
services:
app:
build:
context: . # Dockerfile 所在目录
dockerfile: Dockerfile
args:
NODE_VERSION: 20
cache_from:
- myapp:cache
target: builder # 多阶段构建目标6.2 image / container_name
yaml
services:
app:
image: myapp:1.0 # 使用现有镜像
container_name: myapp # 容器名(避免自动生成)6.3 ports
yaml
ports:
- "3000:3000" # 主机:容器
- "8080:80" # 端口不同
- "127.0.0.1:8080:80" # 指定 IP6.4 environment
yaml
environment:
- NODE_ENV=production
- DB_HOST=db
# 等价
env_file:
- .env6.5 volumes
yaml
volumes:
# 命名卷
- dbdata:/var/lib/mysql
# bind mount
- ./data:/app/data
# 只读
- ./config:/app/config:ro6.6 depends_on(启动顺序)
yaml
services:
app:
depends_on:
db:
condition: service_healthy
cache:
condition: service_started6.7 healthcheck
yaml
services:
app:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s6.8 networks
yaml
services:
app:
networks:
- frontend
- backend
networks:
frontend:
backend:6.9 resources(限制)
yaml
services:
app:
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M6.10 restart
yaml
restart: always
# no / on-failure / unless-stopped / always七、profile(分组启动)
yaml
services:
app:
profiles: [prod]
dev-tools:
profiles: [dev]bash
docker compose --profile dev up
docker compose --profile prod up八、实战:本地开发环境
yaml
# docker-compose.dev.yml
version: '3.8'
services:
app:
build:
target: dev # dev 阶段
volumes:
- .:/app # 同步代码
- /app/node_modules # 排除容器内
command: pnpm run dev
ports:
- "3000:3000"
- "9229:9229" # 调试端口
environment:
- NODE_ENV=development
depends_on:
- db
db:
image: postgres:15-alpine
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
pgdata:九、生产 vs 开发
yaml
# docker-compose.yml(基础)
# docker-compose.override.yml(开发,自动加载)
# docker-compose.prod.yml(生产)bash
# 开发
docker compose up
# 生产
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d十、Swarm 模式(集群)
bash
# 初始化
docker swarm init
# 加入
docker swarm join --token xxx
# stack
docker stack deploy -c docker-compose.yml mystack十一、Compose V2 vs V1
V2 用 docker compose(空格),V1 用 docker-compose(连字符),V2 更快、Go 写的。
十二、本章小结
| 关键 | 说明 |
|---|---|
services | 定义容器 |
volumes | 持久化数据 |
networks | 容器网络 |
depends_on | 启动顺序 |
healthcheck | 健康检查 |
profiles | 分组 |
动手练习
- 编写 app + db + redis + nginx 的 compose
- 用健康检查,确保 db 启动后 app 才启
- 用 named volume 持久化数据
- 用 .env 注入敏感信息
推荐阅读
下一章:第 213 章:Kubernetes 入门 →