Skip to content

Docker Compose 实战指南

什么是 Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具。通过一个 docker-compose.yml 文件配置应用的所有服务,然后使用一个命令即可创建并启动所有服务。

常用命令

bash
# 启动所有服务(后台运行)
docker compose up -d

# 停止所有服务
docker compose down

# 停止并删除数据卷
docker compose down -v

# 查看服务状态
docker compose ps

# 查看服务日志
docker compose logs -f

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

# 重启单个服务
docker compose restart mysql

# 重新构建并启动
docker compose up -d --build

# 拉取最新镜像
docker compose pull

配置文件详解

基础结构

yaml
version: '3.8'  # Compose 文件版本(可选,新版本可省略)

services:       # 服务定义
  service1:
    ...
  service2:
    ...

volumes:        # 数据卷定义(可选)
  ...

networks:       # 网络定义(可选)
  ...

常用配置项

yaml
services:
  app:
    # 镜像名称
    image: nginx:1.25
    
    # 或从 Dockerfile 构建
    build:
      context: .
      dockerfile: Dockerfile
    
    # 容器名称
    container_name: my-app
    
    # 端口映射
    ports:
      - "8080:80"
      - "443:443"
    
    # 环境变量
    environment:
      - NODE_ENV=production
      - DB_HOST=mysql
    
    # 从文件读取环境变量
    env_file:
      - .env
    
    # 数据卷挂载
    volumes:
      - ./data:/app/data           # 绑定挂载
      - app-logs:/var/log          # 命名卷
      - /etc/localtime:/etc/localtime:ro  # 只读挂载
    
    # 依赖关系
    depends_on:
      - mysql
      - redis
    
    # 重启策略
    restart: always   # no | always | on-failure | unless-stopped
    
    # 网络
    networks:
      - backend
    
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
    
    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3

实战模板

1. Spring Boot + MySQL + Redis

yaml
version: '3.8'

services:
  app:
    build: .
    container_name: springboot-app
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=mysql123
      - SPRING_REDIS_HOST=redis
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    container_name: mysql
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=mysql123
      - MYSQL_DATABASE=mydb
      - TZ=Asia/Shanghai
    volumes:
      - mysql-data:/var/lib/mysql
      - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
    networks:
      - app-network

  redis:
    image: redis:7-alpine
    container_name: redis
    ports:
      - "6379:6379"
    command: redis-server --requirepass redis123
    volumes:
      - redis-data:/data
    restart: unless-stopped
    networks:
      - app-network

volumes:
  mysql-data:
  redis-data:

networks:
  app-network:
    driver: bridge

2. 前后端分离项目

yaml
version: '3.8'

services:
  frontend:
    image: nginx:alpine
    container_name: frontend
    ports:
      - "80:80"
    volumes:
      - ./frontend/dist:/usr/share/nginx/html:ro
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - backend
    restart: unless-stopped
    networks:
      - app-network

  backend:
    build: ./backend
    container_name: backend
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    restart: unless-stopped
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

3. 开发环境中间件全家桶

yaml
version: '3.8'

services:
  mysql:
    image: mysql:8.0
    container_name: dev-mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: mysql
      TZ: Asia/Shanghai
    volumes:
      - mysql-data:/var/lib/mysql
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    container_name: dev-redis
    ports:
      - "6379:6379"
    command: redis-server --requirepass redis
    volumes:
      - redis-data:/data
    restart: unless-stopped

  nacos:
    image: nacos/nacos-server:v2.4.3
    container_name: dev-nacos
    ports:
      - "8848:8848"
      - "9848:9848"
    environment:
      MODE: standalone
      TZ: Asia/Shanghai
    restart: unless-stopped

  rabbitmq:
    image: rabbitmq:3-management
    container_name: dev-rabbitmq
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: admin123
    volumes:
      - rabbitmq-data:/var/lib/rabbitmq
    restart: unless-stopped

volumes:
  mysql-data:
  redis-data:
  rabbitmq-data:

高级技巧

使用 .env 文件

创建 .env 文件:

env
MYSQL_ROOT_PASSWORD=secret123
MYSQL_DATABASE=myapp
REDIS_PASSWORD=redis123

docker-compose.yml 中使用:

yaml
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}

多环境配置

bash
# 开发环境
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

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

等待服务就绪

使用 depends_oncondition 配置:

yaml
services:
  app:
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started