Skip to content
第 212 / 250 章运维⏱ 12 分钟阅读

第 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=secret123

4.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.js

5.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"           # 指定 IP

6.4 environment

yaml
environment:
  - NODE_ENV=production
  - DB_HOST=db

# 等价
env_file:
  - .env

6.5 volumes

yaml
volumes:
  # 命名卷
  - dbdata:/var/lib/mysql
  # bind mount
  - ./data:/app/data
  # 只读
  - ./config:/app/config:ro

6.6 depends_on(启动顺序)

yaml
services:
  app:
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started

6.7 healthcheck

yaml
services:
  app:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

6.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: 256M

6.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分组

动手练习

  1. 编写 app + db + redis + nginx 的 compose
  2. 用健康检查,确保 db 启动后 app 才启
  3. 用 named volume 持久化数据
  4. 用 .env 注入敏感信息

推荐阅读


下一章:第 213 章:Kubernetes 入门

本站基于 VitePress 构建 · 由 Codebook 团队维护