一个命令启动整个项目?

问题:一个完整的Web应用通常需要多个服务:

  • Web服务器
  • 数据库
  • 缓存
  • 消息队列

传统方式

docker run -d --name web -p 80:80 nginx
docker run -d --name db -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
docker run -d --name cache redis
...

Docker Compose方式

docker-compose up -d
# 一键启动所有服务!

什么是Docker Compose?

定义:Docker Compose是用于定义和运行多容器Docker应用的工具。

特点

  • 使用YAML文件定义服务
  • 一条命令启动/停止所有服务
  • 自动创建和管理网络
  • 服务之间通过名称互相访问
  • 支持环境变量和配置文件

安装

# 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 Desktop自带
# Windows和Mac用户无需单独安装

验证安装

docker-compose --version

docker-compose.yml基本结构

最简单的示例

version: '3.8'

services:
  web:
    image: nginx
    ports:
      - "80:80"

解释

  • version:Compose文件版本
  • services:定义服务
  • web:服务名称
  • image:使用的镜像
  • ports:端口映射

完整示例

version: '3.8'

services:
  web:
    image: nginx:latest
    container_name: my-web
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
      - ./nginx.conf:/etc/nginx/nginx.conf
    networks:
      - app-network
    environment:
      - TZ=Asia/Shanghai
    restart: unless-stopped

  db:
    image: mysql:8.0
    container_name: my-db
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: mydb
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - app-network
    restart: unless-stopped

  cache:
    image: redis:alpine
    container_name: my-cache
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    networks:
      - app-network
    restart: unless-stopped

networks:
  app-network:
    driver: bridge

volumes:
  mysql-data:
  redis-data:

常用配置项

1. image - 镜像

services:
  web:
    image: nginx:latest
  app:
    image: myapp:v1.0

2. build - 构建镜像

services:
  app:
    build: .
    # 或
    build:
      context: .
      dockerfile: Dockerfile
      args:
        VERSION: 1.0

3. ports - 端口映射

services:
  web:
    ports:
      - "80:80"              # 宿主机80映射到容器80
      - "443:443"
      - "8000-8010:8000-8010"  # 端口范围
      - "127.0.0.1:8080:80"    # 只绑定localhost

4. volumes - 数据卷

services:
  db:
    volumes:
      - db-data:/var/lib/mysql      # 命名卷
      - ./data:/data                 # 绑定挂载
      - /etc/localtime:/etc/localtime:ro  # 只读挂载

volumes:
  db-data:

5. environment - 环境变量

services:
  db:
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=mydb
      # 或
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: mydb

6. env_file - 环境变量文件

services:
  app:
    env_file:
      - .env
      - .env.prod

.env文件内容:

MYSQL_ROOT_PASSWORD=123456
MYSQL_DATABASE=mydb

7. networks - 网络

services:
  web:
    networks:
      - frontend

  db:
    networks:
      - backend

networks:
  frontend:
  backend:

8. depends_on - 依赖关系

services:
  web:
    depends_on:
      - db
      - cache

  db:
    image: mysql:8.0

  cache:
    image: redis:alpine

注意depends_on只控制启动顺序,不等待服务就绪。

9. restart - 重启策略

services:
  web:
    restart: always         # 总是重启
    # 或
    restart: on-failure     # 失败时重启
    # 或
    restart: unless-stopped  # 除非手动停止

10. command - 覆盖启动命令

services:
  app:
    image: python:3.11
    command: python -u app.py
    # 或
    command: ["python", "-u", "app.py"]

Docker Compose常用命令

启动服务

# 启动所有服务
docker-compose up

# 后台运行
docker-compose up -d

# 指定配置文件
docker-compose -f docker-compose.prod.yml up -d

# 启动特定服务
docker-compose up web db

停止服务

# 停止所有服务
docker-compose stop

# 停止特定服务
docker-compose stop web

重启服务

# 重启所有服务
docker-compose restart

# 重启特定服务
docker-compose restart web

删除服务

# 停止并删除所有容器、网络
docker-compose down

# 同时删除数据卷
docker-compose down -v

# 删除特定服务
docker-compose rm -f web

查看日志

# 查看所有服务日志
docker-compose logs

# 查看特定服务日志
docker-compose logs web

# 实时查看日志
docker-compose logs -f

# 查看最近N行
docker-compose logs --tail=100 web

# 查看最近N分钟的日志
docker-compose logs --since=10m web

查看状态

# 查看所有服务状态
docker-compose ps

# 查看服务详细信息
docker-compose config

进入容器

# 进入容器
docker-compose exec web bash

# 在容器内执行命令
docker-compose exec web ls /app

构建镜像

# 构建镜像
docker-compose build

# 构建特定服务镜像
docker-compose build web

# 构建时不使用缓存
docker-compose build --no-cache

实战1:Web应用+数据库

docker-compose.yml

version: '3.8'

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - app
    networks:
      - app-network

  app:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DB_HOST=db
      - DB_NAME=mydb
      - DB_USER=root
      - DB_PASSWORD=123456
    depends_on:
      - db
    networks:
      - app-network

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: mydb
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - app-network

networks:
  app-network:

volumes:
  mysql-data:

使用

# 启动所有服务
docker-compose up -d

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 停止所有服务
docker-compose down

实战2:多环境配置

开发环境(docker-compose.yml)

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    environment:
      - ENV=development
      - DEBUG=true
    command: python -u app.py

生产环境(docker-compose.prod.yml)

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8000:8000"
    environment:
      - ENV=production
      - DEBUG=false
    command: gunicorn -w 4 -b 0.0.0.0:8000 app:app
    restart: unless-stopped

使用

# 开发环境
docker-compose up -d

# 生产环境
docker-compose -f docker-compose.prod.yml up -d

实战3:微服务架构

version: '3.8'

services:
  # API网关
  gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - user-service
      - order-service
      - product-service
    networks:
      - microservices

  # 用户服务
  user-service:
    build: ./user-service
    ports:
      - "8001:8000"
    environment:
      - DB_HOST=user-db
      - REDIS_HOST=cache
    depends_on:
      - user-db
      - cache
    networks:
      - microservices

  user-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE=users
    volumes:
      - user-db-data:/var/lib/mysql
    networks:
      - microservices

  # 订单服务
  order-service:
    build: ./order-service
    ports:
      - "8002:8000"
    environment:
      - DB_HOST=order-db
      - REDIS_HOST=cache
    depends_on:
      - order-db
      - cache
    networks:
      - microservices

  order-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE=orders
    volumes:
      - order-db-data:/var/lib/mysql
    networks:
      - microservices

  # 商品服务
  product-service:
    build: ./product-service
    ports:
      - "8003:8000"
    environment:
      - DB_HOST=product-db
      - REDIS_HOST=cache
    depends_on:
      - product-db
      - cache
    networks:
      - microservices

  product-db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE=products
    volumes:
      - product-db-data:/var/lib/mysql
    networks:
      - microservices

  # 缓存
  cache:
    image: redis:alpine
    volumes:
      - cache-data:/data
    networks:
      - microservices

networks:
  microservices:
    driver: bridge

volumes:
  user-db-data:
  order-db-data:
  product-db-data:
  cache-data:

健康检查

version: '3.8'

services:
  web:
    image: nginx
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:80"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  db:
    image: mysql:8.0
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

配置变量替换

version: '3.8'

services:
  app:
    image: myapp:${APP_VERSION:-latest}
    environment:
      - DB_HOST=${DB_HOST:-localhost}
      - DB_PORT=${DB_PORT:-3306}
    ports:
      - "${APP_PORT:-8000}:8000"

.env文件:

APP_VERSION=v1.0
DB_HOST=db
DB_PORT=3306
APP_PORT=8000

最佳实践

1. 使用版本控制

version: '3.8'  # 明确指定版本

2. 使用命名卷

volumes:
  mysql-data:  # 命名卷,便于管理

3. 使用自定义网络

networks:
  app-network:
    driver: bridge

4. 使用健康检查

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:80"]
  interval: 30s
  timeout: 10s
  retries: 3

5. 多环境配置

docker-compose.yml          # 基础配置
docker-compose.dev.yml     # 开发环境
docker-compose.prod.yml    # 生产环境

本章小结

  • Docker Compose:定义和管理多容器应用
  • 配置文件:docker-compose.yml使用YAML格式
  • 常用命令:up、down、logs、ps、exec
  • 实战场景:Web应用、多环境、微服务
  • 最佳实践:版本控制、命名卷、健康检查

现在已经掌握了Docker Compose,下一章我们来实战打包Python项目!

继续学下去,马上就能做实用项目了!