2025-11-21 Docker Compose实战指南:从开发测试到生产环境部署

Docker Compose作为容器编排的重要工具,极大地简化了多容器应用的管理和部署。本文将全面介绍Docker Compose的使用方法,从基础概念到企业级部署实践。

## Docker Compose基础概念

### Compose文件结构解析

Docker Compose的核心是docker-compose.yml文件,它定义了多容器应用的架构。

```yaml

# docker-compose.yml 基础结构

version: '3.8'

services:

  # 服务定义开始

  web:

    build: .

    ports:

      - "8000:8000"

    environment:

      - DATABASE_URL=postgresql://user:pass@db:5432/app

    depends_on:

      - db

    volumes:

      - .:/app

    networks:

      - app-network

  db:

    image: postgres:13

    environment:

      POSTGRES_DB: app

      POSTGRES_USER: user

      POSTGRES_PASSWORD: pass

    volumes:

      - postgres_data:/var/lib/postgresql/data

    networks:

      - app-network

  redis:

    image: redis:6-alpine

    networks:<"rat.maicaixia.cn">

      - app-network

# 网络定义

networks:

  app-network:

    driver: bridge

# 卷定义

volumes:

  postgres_data:

```

### 基础命令操作

掌握Docker Compose的核心命令是使用的第一步。

```bash

# 启动所有服务

docker-compose up

# 后台启动服务

docker-compose up -d

# 指定compose文件

docker-compose -f docker-compose.prod.yml up -d

# 查看服务状态

docker-compose ps

# 查看服务日志

docker-compose logs

docker-compose logs -f web  # 跟踪web服务日志

# 停止服务

docker-compose down

# 停止服务并删除卷

docker-compose down -v

# 重启服务

docker-compose restart

# 扩展服务实例

docker-compose up -d --scale web=3

# 执行命令

docker-compose exec web bash

docker-compose exec db psql -U user app

```

## 开发环境配置

### 完整的开发环境示例

为开发团队提供标准化的开发环境。

```yaml

# docker-compose<"high.maicaixia.cn">.dev.yml

version: '3.8'

services:

  frontend:

    build:

      context: ./frontend

      dockerfile: Dockerfile.dev

    ports:

      - "3000:3000"

    volumes:

      - ./frontend:/app

      - /app/node_modules

    environment:

      - NODE_ENV=development

      - REACT_APP_API_URL=http://localhost:8000/api

    depends_on:

      - backend

    networks:

      - app-network

  backend:

    build:

      context: ./backend

      dockerfile: Dockerfile.dev

    ports:

      - "8000:8000"

    volumes:

      - ./backend:/app

      - /app/__pycache__

    environment:

      - DEBUG=True

      - DATABASE_URL=postgresql://devuser:devpass@db:5432/devdb

      - REDIS_URL=redis://redis:6379/0

    depends_on:

      - db

      - redis

    networks:

      - app-network

  db:

    image: postgres:13

    environment:

      POSTGRES_DB: devdb

      POSTGRES_USER: devuser

      POSTGRES_PASSWORD: devpass

    ports:

      - "5432:5432"  # 方便本地连接

    volumes:

      - postgres_data:/var/lib/postgresql/data

      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

    networks:

      - app-network

  redis:

    image: redis:6-alpine

    ports:

      - "6379:6379"

    networks:

      - app-network

  # 开发工具

  mailhog:

    image: mailhog/mailhog<"neixit.maicaixia.cn">

    ports:

      - "1025:1025"  # SMTP

      - "8025:8025"  # Web UI

    networks:

      - app-network

volumes:

  postgres_data:

networks:

  app-network:

    driver: bridge

```

### 开发环境启动脚本

```bash

#!/bin/bash

# dev-setup.sh

set -e

echo "=== 开发环境设置 ==="

# 检查Docker是否运行

if ! docker info > /dev/null 2>&1; then

    echo "错误: Docker守护进程未运行"

    exit 1

fi

# 创建环境文件

if [ ! -f .env.dev ]; then

    cat > .env.dev << EOF

# 开发环境配置

COMPOSE_PROJECT_NAME=myapp_dev

DEBUG=True

DATABASE_URL=postgresql://devuser:devpass@db:5432/devdb

REDIS_URL=redis://redis:6379/0

EOF

    echo "创建 .env.dev 文件"

fi

# 构建并启动服务

echo "构建和启动开发环境..."

docker-compose -f docker-compose.dev.yml up -d --build

echo "等待服务启动..."

sleep 10

# 检查服务状态

echo "服务状态:"

docker-compose <"note.maicaixia.cn">-f docker-compose.dev.yml ps

# 运行数据库迁移

echo "运行数据库迁移..."

docker-compose -f docker-compose.dev.yml exec backend python manage.py migrate

echo "开发环境就绪!"

echo "前端: http://localhost:3000"

echo "后端API: http://localhost:8000"

echo "邮件测试: http://localhost:8025"

```

## 生产环境配置

### 生产级Compose配置

生产环境需要关注性能、安全和可靠性。

```yaml

# docker-compose.prod.yml

version: '3.8'

services:

  nginx:

    image: nginx:1.21-alpine

    ports:

      - "80:80"

      - "443:443"

    volumes:

      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro

      - ./ssl:/etc/nginx/ssl:ro

      - static_volume:/app/static

      - media_volume:/app/media

    depends_on:

      - web

    networks:

      - app-network

    restart: unless-stopped

  web:

    build:

      context: .

      dockerfile: Dockerfile.prod

    environment:

      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}

      - REDIS_URL=redis://redis:6379/0

      - DEBUG=False

      - SECRET_KEY<"ill.maicaixia.cn">=${SECRET_KEY}

    volumes:

      - static_volume:/app/static

      - media_volume:/app/media

    depends_on:

      - db

      - redis

    networks:

      - app-network

    restart: unless-stopped

    deploy:

      replicas: 3

      update_config:

        parallelism: 1

        delay: 10s

      restart_policy:

        condition: on-failure

        delay: 5s

        max_attempts: 3

        window: 120s

  celery_worker:

    build:

      context: .

      dockerfile: Dockerfile.prod

    command: celery -A app worker -l info

    environment:

      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}

      - REDIS_URL=redis://redis:6379/0

    depends_on:

      - db

      - redis

    networks:

      - app-network

    restart: unless-stopped

    deploy:

      replicas: 2

  celery_beat:

    build:

      context: .

      dockerfile: Dockerfile.prod

    command: celery -A app beat -l info

    environment:

      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}

      - REDIS_URL=redis://redis:6379/0

    depends_on:

      - db

      - redis

    networks:

      - app-network

    restart: unless-stopped

  db:

    image: postgres:13

    environment:

      POSTGRES_DB: ${DB_NAME}

      POSTGRES_USER: ${DB_USER}

      POSTGRES_PASSWORD: ${DB_PASSWORD}

    volumes:

      - postgres_data:/var/lib/postgresql/data

      - ./backups:/backups

    networks:

      - app-network

    restart: unless-stopped

    command: >

      postgres

      -c shared_preload<"buzzword.maicaixia.cn">_libraries=pg_stat_statements

      -c pg_stat_statements.track=all

      -c max_connections=200

  redis:

    image: redis:6-alpine

    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}

    volumes:

      - redis_data:/data

    networks:

      - app-network

    restart: unless-stopped

volumes:

  postgres_data:

  redis_data:

  static_volume:

  media_volume:

networks:

  app-network:

    driver: bridge

```

### 生产环境部署脚本

```bash

#!/bin/bash

# deploy-prod.sh

set -e

ENV_FILE=".env.prod"

COMPOSE_FILE="docker-compose.prod.yml"

echo "=== 生产环境部署 ==="

# 检查环境文件

if [ ! -f "$ENV_FILE" ]; then

    echo "错误: 找不到环境文件 $ENV_FILE"

    exit 1

fi

# 加载环境变量

export $(grep -v '^#' $ENV_FILE | xargs)

# 创建必要的目录

mkdir -p nginx/ssl backups

# 生成SSL证书(如果不存在)

if [ ! -f nginx/ssl/cert.pem ]; then

    echo "生成自签名SSL证书..."

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \

        -keyout nginx/ssl/key.pem \

        -out nginx/ssl/cert.pem \

        -subj "/C=US/ST<"iron.maicaixia.cn">=State/L=City/O=Org/CN=example.com"

fi

# 停止现有服务

echo "停止现有服务..."

docker-compose -f $COMPOSE_FILE down

# 拉取最新镜像

echo "拉取最新镜像..."

docker-compose -f $COMPOSE_FILE pull

# 启动服务

echo "启动服务..."

docker-compose -f $COMPOSE_FILE up -d

# 健康检查

echo "执行健康检查..."

sleep 30

# 检查服务状态

echo "服务状态:"

docker-compose -f $COMPOSE_FILE ps

# 检查Web服务健康

if curl -f http://localhost/health > /dev/null 2>&1; then

    echo "✓ 应用健康检查通过"

else

    echo "✗ 应用健康检查失败"

    exit 1

fi

echo "生产环境部署完成!"

```

## 多环境配置管理

### 环境特定配置

使用扩展文件管理不同环境的配置。

```yaml

# docker-compose.base.yml - 基础配置

version: '3.8'

services:

  web:

    build: .

    environment:

      - DATABASE_URL=${DATABASE_URL}

      - REDIS_URL=${REDIS_URL}

    networks:

      - app-network

    healthcheck:

      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]

      interval: 30s

      timeout: 10s

      retries: 3

  db:

    image: postgres:13

    environment:

      POSTGRES_DB: ${DB_NAME}

      POSTGRES_USER: ${DB_USER}

      POSTGRES_PASSWORD: ${DB_PASSWORD}

    volumes:

      - postgres_data:/var/lib/postgresql/data

    networks:

      - app-network

networks:

  app-network:

volumes:

  postgres_data:

```

```yaml

# docker-compose.override.yml - 开发环境扩展

version: '3.8'

services:

  web:

    build:

      context: .

      dockerfile: Dockerfile.dev

    ports:

      - "8000:8000"

    volumes:

      - .:/app

    environment:

      - DEBUG=True

      - RELOAD=True

  db:

    ports:

      - "5432:5432"

```

```yaml

# docker-compose.prod.yml<"snake.maicaixia.cn"> - 生产环境扩展

version: '3.8'

services:

  web:

    build:

      context: .

      dockerfile: Dockerfile.prod

    restart: unless-stopped

    deploy:

      replicas: 3

  nginx:

    image: nginx:1.21-alpine

    ports:

      - "80:80"

      - "443:443"

    volumes:

      - ./nginx.conf:/etc/nginx/nginx.conf:ro

    depends_on:

      - web

    networks:

      - app-network

    restart: unless-stopped

```

### 环境配置脚本

```bash

#!/bin/bash

# env-setup.sh

ENVIRONMENT=${1:-dev}

case $ENVIRONMENT in

    dev)

        ENV_FILE=".env.dev"

        COMPOSE_FILES="-f docker-compose.base.yml -f docker-compose.override.yml"

        ;;

    staging)

        ENV_FILE=".env.staging"

        COMPOSE_FILES="-f docker-compose.base.yml -f docker-compose.staging.yml"

        ;;

    prod)

        ENV_FILE=".env.prod"

        COMPOSE_FILES="-f docker-compose.base.yml -f docker-compose.prod.yml"

        ;;

    *)

        echo "用法: $0 {dev|staging|prod}"

        exit 1

        ;;

esac

if [ ! -f "$ENV_FILE" ]; then

    echo "错误: 找不到环境文件 $ENV_FILE"

    echo "请从模板创建: cp .env.example $ENV_FILE"

    exit 1

fi

# 设置环境变量

export COMPOSE_PROJECT_NAME="myapp_${ENVIRONMENT}"

export $(grep -v '^#' $ENV_FILE | xargs)

echo "环境: $ENVIRONMENT"

echo "项目: $COMPOSE_PROJECT_NAME"

# 执行docker-compose命令

shift

docker-compose $COMPOSE_FILES "$@"

```

## 企业级部署实践

### 高可用架构

构建支持高可用的生产环境。

```yaml

# docker-compose.ha.yml

version: '3.8'

services:

  haproxy:

    image: haproxy:2.4

    ports:

      - "80:80"

      - "443:443"

    volumes:

      - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro

      - ./ssl:/etc/ssl:ro

    networks:

      - app-network

    restart: unless-stopped

    deploy:

      replicas: 2

  web:

    build: .

    environment:

      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}

      - REDIS_URL=redis://redis:6379/0

    networks:

      - app-network

    restart: unless-<"tree.maicaixia.cn">stopped

    deploy:

      replicas: 5

      update_config:

        parallelism: 2

        delay: 10s

        order: start-first

      rollback_config:

        parallelism: 0

        order: stop-first

      restart_policy:

        condition: any

        delay: 5s

        max_attempts: 3

        window: 120s

      resources:

        limits:

          cpus: '1'

          memory: 1G

        reservations:

          cpus: '0.5'

          memory: 512M

  db:

    image: postgres:13

    environment:

      POSTGRES_DB: ${DB_NAME}

      POSTGRES_USER: ${DB_USER}

      POSTGRES_PASSWORD: ${DB_PASSWORD}

    volumes:

      - postgres_data:/var/lib/postgresql/data

    networks:

      - app-network

    restart: unless-stopped

    deploy:

      placement:

        constraints:

          - node.role == manager

  redis:

    image: redis:6-alpine

    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}

    volumes:

      - redis_data:/data

    networks:

      - app-network

    restart: unless-stopped

    deploy:

      replicas: 3

volumes:

  postgres_data:

    driver: local

  redis_data:

    driver: local

networks:

  app-network:

    driver: overlay

    attachable: true

```

### 监控和日志管理

集成监控和日志收集。

```yaml

# docker-compose.monitoring.yml

version: '3.8'

services:

  prometheus:

    image: prom/prometheus

    ports:

      - "9090:9090"

    volumes:

      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro

      - prometheus_data:/prometheus

    command:

      - '--config.file=/etc/prometheus/prometheus.yml'

      - '--storage.tsdb.path=/prometheus'

      - '--web.console.libraries=/etc/prometheus/console_libraries'

      - '--web.console.templates=/etc/prometheus/console_templates'

      - '--storage.tsdb.retention.time=200h'

      - '--web.enable-lifecycle'

    networks:

      - monitoring

    restart: unless-stopped

  grafana:

    image: grafana/grafana

    ports:

      - "3000:3000"

    environment:

      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}

    volumes:

      - grafana_data:/var/lib/grafana

      - ./grafana/dashboards:/etc/grafana/provisioning/dashboards

      - ./grafana/datasources:/etc/grafana/provisioning/datasources

    networks:

      - monitoring

    restart: unless-stopped

    depends_on:

      - prometheus

  node-exporter:

    image: prom/node-exporter

    volumes:

      - /proc:/host/proc:ro

      - /sys:/host/sys:ro

      - /:/rootfs:ro

    command:

      - '--path.procfs=/host/proc'

      - '--path.sysfs=/host/sys'

      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'

    networks:

      - monitoring

    restart: unless-stopped

    deploy:

      mode: global

  cadvisor:

    image: gcr.io/cadvisor/cadvisor

    volumes:

      - /:/rootfs:ro

      - /var/run:/var/run:ro

      - /sys:/sys:ro

      - /var/lib/docker/:/var/lib/docker:ro

      - /dev/disk/:/dev/disk:ro

    ports:

      - "8080:8080"

    networks:

      - monitoring

    restart: unless<"fomo.maicaixia.cn">-stopped

    deploy:

      mode: global

volumes:

  prometheus_data:

  grafana_data:

networks:

  monitoring:

    driver: overlay

```

## 安全最佳实践

### 安全加固配置

```yaml

# docker-compose.secure.yml

version: '3.8'

services:

  web:

    build: .

    user: "1000:1000"  # 非root用户

    read_only: true

    security_opt:

      - no-new-privileges:true

    tmpfs:

      - /tmp

      - /var/tmp

    cap_drop:

      - ALL

    cap_add:

      - CHOWN

      - SETGID

      - SETUID

    environment:

      - DB_USER_FILE=/run/secrets/db_user

      - DB_PASSWORD_FILE=/run/secrets/db_password

    secrets:

      - db_user

      - db_password

    networks:

      - app-network

  db:

    image: postgres:13

    user: "999:999"  # postgres用户

    read_only: false

    security_opt:

      - no-new-privileges:true

    environment:

      POSTGRES_DB: myapp

      POSTGRES_USER_FILE: /run/secrets/db_user

      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

    secrets:

      - db_user

      - db_password

    volumes:

      - postgres_data:/var/lib/postgresql/data

    networks:

      - app-network

secrets:

  db_user:

    file: ./secrets/db_user.txt

  db_password:

    file: ./secrets/db_password.txt

volumes:

  postgres_data:

networks:

  app-network:

    driver: bridge

```

### 安全部署脚本

```bash

#!/bin/bash

# secure-deploy.sh

set -e

echo "=== 安全部署检查 ==="

# 检查敏感文件权限

check_file_permissions() {

    local file=$1

    if [ -f "$file" ]; then

        local perm=$(stat -c "%a" "$file")

        if [ "$perm" -gt 600 ]; then

            echo "警告: $file 权限过宽 ($perm)"

            return 1

        fi

    fi

}

# 检查环境变量

check_env_vars() {

    local env_file=$1

    if grep -q "PASSWORD\|SECRET\|KEY" "$env_file"; then

        echo "警告: $env_file 包含敏感信息"

        echo "建议使用Docker Secrets"

    fi

}

# 检查镜像签名

check_image_security() {

    local image=$1

    if ! docker trust inspect "$image" > /dev/null 2>&1; then

        echo "警告: $image 未签名"

    fi

}

# 执行检查

check_file_permissions ".env.prod"

check_env_vars ".env.prod"

echo "安全检查完成"

```

## 持续集成与部署

### CI/CD集成示例

```yaml

# .gitlab-ci.yml

stages:

  - test

  - build

  - deploy

variables:

  DOCKER_HOST: tcp://docker:2375

  DOCKER_DRIVER: overlay2

services:

  - docker:dind

before_script:

  - apk add --no-cache docker-compose

test:

  stage: test

  script:

    - docker-compose -f docker-compose.test.yml up -d

    - docker-compose -f docker-compose.test.yml exec web pytest

    - docker-compose -f docker-compose.test.yml down

build:

  stage: build

  script:

    - docker-compose -f docker-compose.prod.yml build

    - docker tag myapp_web:latest registry.example.com/myapp/web:${CI_COMMIT_SHA}

    - docker push registry.example.com/myapp/web:${CI_COMMIT_SHA}

  only:

    - main

deploy:

  stage: deploy

  script:

    - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin

    - docker-compose -f docker-compose.prod.yml pull

    - docker-compose -f docker-compose.prod.yml up -d

    - docker-compose -f docker-compose.prod.yml exec web python manage.py migrate

  environment:

    name: production

    url: https://example.com

  only:

    - main

```

## 结语

Docker Compose作为容器化应用部署的重要工具,从简单的开发环境到复杂的企业级生产部署都能提供有力支持。通过合理的配置管理、安全加固和自动化部署,可以构建出稳定、可靠、易维护的容器化应用架构。

掌握Docker Compose的进阶特性,结合企业实际需求制定合适的部署策略,将显著提升应用交付的效率和质量。随着云原生技术的发展,Docker Compose仍然是容器编排领域不可或缺的重要工具。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容