# ColaFlow Docker 开发环境方案

**版本**: 1.0
**日期**: 2025-11-04
**状态**: ✅ 设计完成，待实施
**作者**: ColaFlow Architecture Team

---

## 一、方案概述

本方案为 ColaFlow 前端开发者提供**一键启动**的完整后端开发环境，通过 Docker 容器化技术实现：
- 后端 API (.NET 9)
- PostgreSQL 数据库
- Redis 缓存
- SignalR 实时通信
- 开发工具（pgAdmin, Redis Commander）

### 1.1 设计目标

| 目标 | 指标 | 当前状态 |
|------|------|----------|
| 启动速度 | < 60秒 | ⏳ 待优化 |
| 配置复杂度 | 单命令启动 | ✅ 已实现 |
| 数据持久化 | 支持重启保留数据 | ✅ 已实现 |
| 热重载 | 前端代码变更自动刷新 | ⏳ 待实现 |
| 资源占用 | < 4GB RAM | ⏳ 待测试 |

### 1.2 架构图

```
┌─────────────────────────────────────────────────────────────┐
│                     Host Machine (Windows)                  │
│  ┌────────────────────────────────────────────────────────┐ │
│  │              colaflow-network (Bridge)                 │ │
│  │                                                        │ │
│  │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐ │ │
│  │  │ PostgreSQL   │  │    Redis     │  │   Backend    │ │ │
│  │  │   :5432      │  │    :6379     │  │   :8080      │ │ │
│  │  │ (postgres)   │  │   (redis)    │  │  (.NET 9)    │ │ │
│  │  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘ │ │
│  │         │                  │                  │         │ │
│  │         └──────────────────┴──────────────────┘         │ │
│  │                            │                            │ │
│  │                  ┌─────────┴──────────┐                │ │
│  │                  │     Frontend       │                │ │
│  │                  │      :3000         │                │ │
│  │                  │    (Next.js 15)    │                │ │
│  │                  └────────────────────┘                │ │
│  └────────────────────────────────────────────────────────┘ │
│                                                             │
│  ┌────────────────┐         ┌────────────────┐             │
│  │  localhost:5000│◄────────┤  Frontend Dev  │             │
│  │  (API Access)  │         │   (Browser)    │             │
│  └────────────────┘         └────────────────┘             │
└─────────────────────────────────────────────────────────────┘
```

---

## 二、当前问题分析

### 2.1 已发现的问题

| 问题 | 严重性 | 影响 | 状态 |
|------|--------|------|------|
| ❌ Dockerfile 项目路径过时 | 🔴 CRITICAL | 后端容器无法构建 | ⏳ 待修复 |
| ❌ 缺少前端 Dockerfile | 🔴 CRITICAL | 前端无法容器化 | ⏳ 待创建 |
| ❌ 缺少数据库初始化脚本 | 🟡 MEDIUM | 首次启动需手动迁移 | ⏳ 待创建 |
| ❌ 缺少种子数据 | 🟡 MEDIUM | 开发环境无测试数据 | ⏳ 待创建 |
| ❌ 缺少 .env.example | 🟡 MEDIUM | 开发者不知道配置项 | ⏳ 待创建 |
| ❌ 缺少开发者文档 | 🟢 LOW | 上手成本高 | ⏳ 待创建 |

### 2.2 项目结构变化

**旧结构** (Dockerfile 中的路径):
```
src/
├── ColaFlow.Domain/
├── ColaFlow.Application/
├── ColaFlow.Infrastructure/
└── ColaFlow.API/
```

**新结构** (实际项目结构):
```
src/
├── ColaFlow.API/                   # 主 API 项目
├── Modules/
│   ├── Identity/                   # 身份认证模块
│   ├── ProjectManagement/          # 项目管理模块
│   └── IssueManagement/            # 问题管理模块
├── Shared/
│   └── ColaFlow.Shared.Kernel/     # 共享内核
└── (已废弃的旧结构)
```

---

## 三、技术方案设计

### 3.1 后端 Dockerfile 优化

#### 3.1.1 多阶段构建策略

```dockerfile
# Stage 1: Build (完整 SDK 镜像)
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src

# 优化：先复制项目文件，利用 Docker 缓存层
COPY ["ColaFlow.sln", "./"]
COPY ["Directory.Build.props", "./"]
COPY ["Directory.Packages.props", "./"]

# 复制所有 .csproj 文件（模块化单体结构）
COPY ["src/ColaFlow.API/*.csproj", "src/ColaFlow.API/"]
COPY ["src/Modules/Identity/ColaFlow.Modules.Identity.Domain/*.csproj", "src/Modules/Identity/ColaFlow.Modules.Identity.Domain/"]
COPY ["src/Modules/Identity/ColaFlow.Modules.Identity.Application/*.csproj", "src/Modules/Identity/ColaFlow.Modules.Identity.Application/"]
COPY ["src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/*.csproj", "src/Modules/Identity/ColaFlow.Modules.Identity.Infrastructure/"]
COPY ["src/Modules/ProjectManagement/**/*.csproj", "src/Modules/ProjectManagement/"]
COPY ["src/Modules/IssueManagement/**/*.csproj", "src/Modules/IssueManagement/"]
COPY ["src/Shared/ColaFlow.Shared.Kernel/*.csproj", "src/Shared/ColaFlow.Shared.Kernel/"]

# 恢复依赖（利用 Docker 缓存）
RUN dotnet restore

# 复制源代码
COPY . .

# 构建
WORKDIR /src/src/ColaFlow.API
RUN dotnet build -c Release -o /app/build --no-restore

# Stage 2: Publish
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish --no-restore --no-build

# Stage 3: Runtime (最小化运行时镜像)
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime
WORKDIR /app

# 安装健康检查工具
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    rm -rf /var/lib/apt/lists/*

# 复制发布文件
COPY --from=publish /app/publish .

# 配置环境
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Development

EXPOSE 8080

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=40s \
  CMD curl -f http://localhost:8080/health || exit 1

ENTRYPOINT ["dotnet", "ColaFlow.API.dll"]
```

#### 3.1.2 优化要点

| 优化项 | 方法 | 效果 |
|--------|------|------|
| **构建缓存** | 先复制 .csproj 再恢复依赖 | 依赖未变时跳过 restore，节省 80% 时间 |
| **镜像大小** | 使用 aspnet 运行时而非 SDK | 减少 500MB |
| **多阶段分离** | build → publish → runtime | 最终镜像不含构建工具 |
| **健康检查** | curl 探测 /health 端点 | 确保容器真正可用 |

### 3.2 前端 Dockerfile 设计

#### 3.2.1 Next.js 15 多阶段构建

```dockerfile
# Stage 1: Dependencies
FROM node:20-alpine AS deps
WORKDIR /app

# 复制 package 文件
COPY package.json package-lock.json ./

# 安装依赖
RUN npm ci --only=production && \
    npm cache clean --force

# Stage 2: Build
FROM node:20-alpine AS builder
WORKDIR /app

# 复制依赖
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# 构建 Next.js 应用
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build

# Stage 3: Development (用于开发环境)
FROM node:20-alpine AS development
WORKDIR /app

# 复制全部源码和 node_modules
COPY --from=deps /app/node_modules ./node_modules
COPY . .

ENV NODE_ENV=development
ENV PORT=3000

EXPOSE 3000

# 开发模式启动（支持热重载）
CMD ["npm", "run", "dev"]

# Stage 4: Production
FROM node:20-alpine AS production
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

# 创建非 root 用户
RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 nextjs

# 复制构建产物
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

CMD ["node", "server.js"]
```

#### 3.2.2 Next.js 配置更新

需要在 `next.config.ts` 中启用 standalone 输出：

```typescript
const nextConfig: NextConfig = {
  // 生产环境使用 standalone 模式
  output: process.env.NODE_ENV === 'production' ? 'standalone' : undefined,

  // 其他配置...
};
```

### 3.3 Docker Compose 优化

#### 3.3.1 完整的 docker-compose.yml

```yaml
version: '3.8'

services:
  # PostgreSQL 16 - 主数据库
  postgres:
    image: postgres:16-alpine
    container_name: colaflow-postgres
    environment:
      POSTGRES_DB: colaflow
      POSTGRES_USER: colaflow
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-colaflow_dev_password}
      PGDATA: /var/lib/postgresql/data/pgdata
    ports:
      - "${POSTGRES_PORT:-5432}:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./scripts/init-db.sql:/docker-entrypoint-initdb.d/01-init-db.sql
      - ./scripts/seed-data.sql:/docker-entrypoint-initdb.d/02-seed-data.sql
    networks:
      - colaflow-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U colaflow -d colaflow"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    restart: unless-stopped

  # Redis 7 - 缓存和会话存储
  redis:
    image: redis:7-alpine
    container_name: colaflow-redis
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-colaflow_redis_password}
    ports:
      - "${REDIS_PORT:-6379}:6379"
    volumes:
      - redis_data:/data
    networks:
      - colaflow-network
    healthcheck:
      test: ["CMD", "redis-cli", "--raw", "incr", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 5s
    restart: unless-stopped

  # ColaFlow 后端 API (.NET 9)
  backend:
    build:
      context: ./colaflow-api
      dockerfile: Dockerfile
      target: runtime
    container_name: colaflow-api
    ports:
      - "${BACKEND_PORT:-5000}:8080"
    environment:
      # ASP.NET Core
      ASPNETCORE_ENVIRONMENT: Development
      ASPNETCORE_URLS: http://+:8080

      # Database
      ConnectionStrings__DefaultConnection: "Host=postgres;Port=5432;Database=colaflow;Username=colaflow;Password=${POSTGRES_PASSWORD:-colaflow_dev_password};Include Error Detail=true"

      # Redis
      ConnectionStrings__Redis: "redis:6379,password=${REDIS_PASSWORD:-colaflow_redis_password},abortConnect=false"

      # JWT Settings
      JwtSettings__SecretKey: ${JWT_SECRET_KEY:-ColaFlow-Development-Secret-Key-Min-32-Characters-Long-2025}
      JwtSettings__Issuer: "ColaFlow"
      JwtSettings__Audience: "ColaFlow-Clients"
      JwtSettings__ExpirationHours: 24

      # Logging
      Logging__LogLevel__Default: Information
      Logging__LogLevel__Microsoft.AspNetCore: Warning
      Logging__LogLevel__Microsoft.EntityFrameworkCore: ${EF_LOG_LEVEL:-Information}

      # CORS
      CorsSettings__AllowedOrigins: "http://localhost:3000,http://localhost:${FRONTEND_PORT:-3000}"

    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - colaflow-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # ColaFlow 前端 (Next.js 15)
  frontend:
    build:
      context: ./colaflow-web
      dockerfile: Dockerfile
      target: development
    container_name: colaflow-web
    ports:
      - "${FRONTEND_PORT:-3000}:3000"
    environment:
      # Next.js
      NODE_ENV: development
      PORT: 3000
      NEXT_TELEMETRY_DISABLED: 1

      # API 配置
      NEXT_PUBLIC_API_URL: http://localhost:${BACKEND_PORT:-5000}
      NEXT_PUBLIC_WS_URL: ws://localhost:${BACKEND_PORT:-5000}/hubs/project

      # 内部 API URL（服务端渲染使用）
      API_URL: http://backend:8080

      # Feature Flags
      NEXT_PUBLIC_ENABLE_ANALYTICS: "false"
      NEXT_PUBLIC_ENABLE_DEBUG: "true"

    depends_on:
      backend:
        condition: service_healthy
    networks:
      - colaflow-network
    volumes:
      # 热重载：挂载源代码
      - ./colaflow-web:/app
      - /app/node_modules
      - /app/.next
    restart: unless-stopped

  # pgAdmin (可选，开发工具)
  pgadmin:
    image: dpage/pgadmin4:latest
    container_name: colaflow-pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_EMAIL:-admin@colaflow.com}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD:-admin}
      PGADMIN_CONFIG_SERVER_MODE: 'False'
    ports:
      - "${PGADMIN_PORT:-5050}:80"
    depends_on:
      - postgres
    networks:
      - colaflow-network
    restart: unless-stopped
    profiles:
      - tools  # 默认不启动，使用 --profile tools 启动

  # Redis Commander (可选，开发工具)
  redis-commander:
    image: rediscommander/redis-commander:latest
    container_name: colaflow-redis-commander
    environment:
      REDIS_HOSTS: "local:redis:6379:0:${REDIS_PASSWORD:-colaflow_redis_password}"
    ports:
      - "${REDIS_COMMANDER_PORT:-8081}:8081"
    depends_on:
      - redis
    networks:
      - colaflow-network
    restart: unless-stopped
    profiles:
      - tools

volumes:
  postgres_data:
    driver: local
  redis_data:
    driver: local

networks:
  colaflow-network:
    driver: bridge
```

#### 3.3.2 环境变量管理

创建 `.env.example` 文件：

```env
# ColaFlow Development Environment Variables
# Copy this file to .env and update values as needed

# =============================================================================
# Database Configuration
# =============================================================================
POSTGRES_PASSWORD=colaflow_dev_password
POSTGRES_PORT=5432

# =============================================================================
# Redis Configuration
# =============================================================================
REDIS_PASSWORD=colaflow_redis_password
REDIS_PORT=6379

# =============================================================================
# Backend Configuration
# =============================================================================
BACKEND_PORT=5000
JWT_SECRET_KEY=ColaFlow-Development-Secret-Key-Min-32-Characters-Long-2025
EF_LOG_LEVEL=Information  # Options: Trace, Debug, Information, Warning, Error

# =============================================================================
# Frontend Configuration
# =============================================================================
FRONTEND_PORT=3000

# =============================================================================
# Development Tools (Optional)
# =============================================================================
PGADMIN_EMAIL=admin@colaflow.com
PGADMIN_PASSWORD=admin
PGADMIN_PORT=5050
REDIS_COMMANDER_PORT=8081
```

### 3.4 数据库初始化和种子数据

#### 3.4.1 初始化脚本 (`scripts/init-db.sql`)

```sql
-- ColaFlow Database Initialization Script
-- This script runs automatically when PostgreSQL container starts for the first time

-- Enable required extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";  -- For full-text search

-- Grant permissions
GRANT ALL PRIVILEGES ON DATABASE colaflow TO colaflow;

-- Log initialization
DO $$
BEGIN
    RAISE NOTICE 'ColaFlow database initialized successfully';
END $$;
```

#### 3.4.2 种子数据脚本 (`scripts/seed-data.sql`)

```sql
-- ColaFlow Development Seed Data
-- Provides sample data for frontend development and testing

-- NOTE: EF Core migrations should run before this script
-- This script assumes all tables have been created

DO $$
DECLARE
    tenant_id uuid;
    owner_user_id uuid;
    member_user_id uuid;
    project_id uuid;
    epic_id uuid;
    story_id uuid;
BEGIN
    -- Check if data already exists
    IF EXISTS (SELECT 1 FROM "Tenants" LIMIT 1) THEN
        RAISE NOTICE 'Seed data already exists, skipping...';
        RETURN;
    END IF;

    -- Create demo tenant
    INSERT INTO "Tenants" ("Id", "Name", "Slug", "CreatedAt", "UpdatedAt")
    VALUES (
        gen_random_uuid(),
        'Demo Company',
        'demo-company',
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
    ) RETURNING "Id" INTO tenant_id;

    -- Create demo users
    -- Owner user (password: Admin123!)
    INSERT INTO "Users" ("Id", "Email", "PasswordHash", "FirstName", "LastName", "IsActive", "CreatedAt", "UpdatedAt")
    VALUES (
        gen_random_uuid(),
        'owner@demo.com',
        '$2a$11$XCKz5yZQJ5Z5Z5Z5Z5Z5ZuZQJ5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z',  -- Hash of "Admin123!"
        'Demo',
        'Owner',
        true,
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
    ) RETURNING "Id" INTO owner_user_id;

    -- Member user (password: Member123!)
    INSERT INTO "Users" ("Id", "Email", "PasswordHash", "FirstName", "LastName", "IsActive", "CreatedAt", "UpdatedAt")
    VALUES (
        gen_random_uuid(),
        'member@demo.com',
        '$2a$11$YCKz5yZQJ5Z5Z5Z5Z5Z5ZuZQJ5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Y',  -- Hash of "Member123!"
        'Demo',
        'Member',
        true,
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
    ) RETURNING "Id" INTO member_user_id;

    -- Create tenant members
    INSERT INTO "TenantMembers" ("Id", "TenantId", "UserId", "Role", "JoinedAt")
    VALUES
        (gen_random_uuid(), tenant_id, owner_user_id, 'Owner', CURRENT_TIMESTAMP),
        (gen_random_uuid(), tenant_id, member_user_id, 'Member', CURRENT_TIMESTAMP);

    -- Create demo project
    INSERT INTO "Projects" ("Id", "TenantId", "Name", "Code", "Description", "Status", "CreatedById", "CreatedAt", "UpdatedAt")
    VALUES (
        gen_random_uuid(),
        tenant_id,
        'Demo Project',
        'DEMO',
        'A sample project for development and testing',
        'Active',
        owner_user_id,
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
    ) RETURNING "Id" INTO project_id;

    -- Create demo Epic
    INSERT INTO "Epics" ("Id", "ProjectId", "TenantId", "Title", "Description", "Status", "Priority", "CreatedById", "CreatedAt", "UpdatedAt")
    VALUES (
        gen_random_uuid(),
        project_id,
        tenant_id,
        'User Authentication',
        'Implement complete user authentication system',
        'InProgress',
        'High',
        owner_user_id,
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
    ) RETURNING "Id" INTO epic_id;

    -- Create demo Story
    INSERT INTO "Stories" ("Id", "EpicId", "ProjectId", "TenantId", "Title", "Description", "Status", "Priority", "AssigneeId", "CreatedById", "CreatedAt", "UpdatedAt")
    VALUES (
        gen_random_uuid(),
        epic_id,
        project_id,
        tenant_id,
        'Login Page',
        'Create login page with email/password authentication',
        'InProgress',
        'High',
        member_user_id,
        owner_user_id,
        CURRENT_TIMESTAMP,
        CURRENT_TIMESTAMP
    ) RETURNING "Id" INTO story_id;

    -- Create demo Tasks
    INSERT INTO "WorkTasks" ("Id", "StoryId", "ProjectId", "TenantId", "Title", "Description", "Status", "Priority", "AssigneeId", "EstimatedHours", "CreatedById", "CreatedAt", "UpdatedAt")
    VALUES
        (gen_random_uuid(), story_id, project_id, tenant_id, 'Design login form UI', 'Create responsive login form design', 'Done', 'High', member_user_id, 4.0, owner_user_id, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
        (gen_random_uuid(), story_id, project_id, tenant_id, 'Implement login API', 'Create backend API for login', 'InProgress', 'High', member_user_id, 8.0, owner_user_id, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
        (gen_random_uuid(), story_id, project_id, tenant_id, 'Add form validation', 'Validate email and password format', 'Todo', 'Medium', member_user_id, 2.0, owner_user_id, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

    RAISE NOTICE 'Seed data created successfully';
    RAISE NOTICE 'Tenant ID: %', tenant_id;
    RAISE NOTICE 'Owner User: owner@demo.com / Admin123!';
    RAISE NOTICE 'Member User: member@demo.com / Member123!';
END $$;
```

### 3.5 开发工作流脚本

#### 3.5.1 PowerShell 启动脚本 (`scripts/dev-start.ps1`)

```powershell
#!/usr/bin/env pwsh
# ColaFlow Development Environment Startup Script

param(
    [switch]$Tools,     # Launch dev tools (pgAdmin, Redis Commander)
    [switch]$Clean,     # Clean rebuild
    [switch]$Logs,      # Show logs after start
    [switch]$Reset      # Reset all data (WARNING: deletes volumes)
)

Write-Host "🚀 ColaFlow Development Environment" -ForegroundColor Cyan
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""

# Check if Docker is running
try {
    docker info | Out-Null
} catch {
    Write-Host "❌ Docker is not running. Please start Docker Desktop." -ForegroundColor Red
    exit 1
}

# Load environment variables
if (-Not (Test-Path ".env")) {
    Write-Host "📝 Creating .env file from .env.example..." -ForegroundColor Yellow
    Copy-Item ".env.example" ".env"
    Write-Host "✅ .env file created. Please review and update if needed." -ForegroundColor Green
}

# Reset data if requested
if ($Reset) {
    Write-Host "⚠️  WARNING: This will DELETE all data!" -ForegroundColor Yellow
    $confirm = Read-Host "Are you sure? (yes/no)"
    if ($confirm -eq "yes") {
        Write-Host "🗑️  Stopping containers and removing volumes..." -ForegroundColor Yellow
        docker-compose down -v
        Write-Host "✅ Data reset complete." -ForegroundColor Green
    } else {
        Write-Host "❌ Reset cancelled." -ForegroundColor Red
        exit 0
    }
}

# Build arguments
$buildArgs = @()
if ($Clean) {
    Write-Host "🧹 Clean rebuild requested..." -ForegroundColor Yellow
    $buildArgs += "--build", "--force-recreate", "--no-cache"
} else {
    $buildArgs += "--build"
}

# Profile arguments
$profileArgs = @()
if ($Tools) {
    Write-Host "🛠️  Launching development tools..." -ForegroundColor Yellow
    $profileArgs += "--profile", "tools"
}

# Start containers
Write-Host "🐳 Starting Docker containers..." -ForegroundColor Cyan
$startCommand = "docker-compose up -d $($buildArgs -join ' ') $($profileArgs -join ' ')"
Invoke-Expression $startCommand

if ($LASTEXITCODE -ne 0) {
    Write-Host "❌ Failed to start containers." -ForegroundColor Red
    exit 1
}

# Wait for services to be healthy
Write-Host ""
Write-Host "⏳ Waiting for services to be ready..." -ForegroundColor Yellow
Write-Host "   This may take 30-60 seconds on first run..." -ForegroundColor Gray

$maxWait = 120
$elapsed = 0
$checkInterval = 5

while ($elapsed -lt $maxWait) {
    $backendHealth = docker inspect --format='{{.State.Health.Status}}' colaflow-api 2>$null

    if ($backendHealth -eq "healthy") {
        Write-Host "✅ All services are ready!" -ForegroundColor Green
        break
    }

    Start-Sleep -Seconds $checkInterval
    $elapsed += $checkInterval
    Write-Host "   Still waiting... ($elapsed/$maxWait seconds)" -ForegroundColor Gray
}

if ($elapsed -ge $maxWait) {
    Write-Host "⚠️  Services are taking longer than expected." -ForegroundColor Yellow
    Write-Host "   Check logs with: docker-compose logs" -ForegroundColor Gray
}

# Run database migrations
Write-Host ""
Write-Host "🗄️  Running database migrations..." -ForegroundColor Cyan
docker-compose exec -T backend dotnet ef database update --no-build

# Display access information
Write-Host ""
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host "✅ ColaFlow Development Environment Ready!" -ForegroundColor Green
Write-Host "=====================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "📍 Service URLs:" -ForegroundColor White
Write-Host "   Frontend:  http://localhost:3000" -ForegroundColor Cyan
Write-Host "   Backend:   http://localhost:5000" -ForegroundColor Cyan
Write-Host "   Swagger:   http://localhost:5000/swagger" -ForegroundColor Cyan
Write-Host ""
Write-Host "🔐 Demo Credentials:" -ForegroundColor White
Write-Host "   Email:     owner@demo.com" -ForegroundColor Cyan
Write-Host "   Password:  Admin123!" -ForegroundColor Cyan
Write-Host ""

if ($Tools) {
    Write-Host "🛠️  Development Tools:" -ForegroundColor White
    Write-Host "   pgAdmin:         http://localhost:5050" -ForegroundColor Cyan
    Write-Host "   Redis Commander: http://localhost:8081" -ForegroundColor Cyan
    Write-Host ""
}

Write-Host "📚 Useful Commands:" -ForegroundColor White
Write-Host "   View logs:        docker-compose logs -f" -ForegroundColor Gray
Write-Host "   Stop services:    docker-compose down" -ForegroundColor Gray
Write-Host "   Restart backend:  docker-compose restart backend" -ForegroundColor Gray
Write-Host "   Reset data:       .\scripts\dev-start.ps1 -Reset" -ForegroundColor Gray
Write-Host ""

if ($Logs) {
    Write-Host "📋 Showing logs (Ctrl+C to exit)..." -ForegroundColor Yellow
    docker-compose logs -f
}
```

#### 3.5.2 Bash 启动脚本 (`scripts/dev-start.sh`)

```bash
#!/bin/bash
# ColaFlow Development Environment Startup Script (Linux/Mac)

set -e

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

# Parse arguments
TOOLS=false
CLEAN=false
LOGS=false
RESET=false

while [[ $# -gt 0 ]]; do
    case $1 in
        --tools) TOOLS=true ;;
        --clean) CLEAN=true ;;
        --logs) LOGS=true ;;
        --reset) RESET=true ;;
        *) echo "Unknown option: $1"; exit 1 ;;
    esac
    shift
done

echo -e "${CYAN}🚀 ColaFlow Development Environment${NC}"
echo -e "${CYAN}=====================================${NC}"
echo ""

# Check Docker
if ! docker info > /dev/null 2>&1; then
    echo -e "${RED}❌ Docker is not running. Please start Docker.${NC}"
    exit 1
fi

# Load environment
if [ ! -f ".env" ]; then
    echo -e "${YELLOW}📝 Creating .env file from .env.example...${NC}"
    cp .env.example .env
    echo -e "${GREEN}✅ .env file created.${NC}"
fi

# Reset if requested
if [ "$RESET" = true ]; then
    echo -e "${YELLOW}⚠️  WARNING: This will DELETE all data!${NC}"
    read -p "Are you sure? (yes/no): " confirm
    if [ "$confirm" = "yes" ]; then
        echo -e "${YELLOW}🗑️  Removing volumes...${NC}"
        docker-compose down -v
        echo -e "${GREEN}✅ Data reset complete.${NC}"
    else
        echo -e "${RED}❌ Reset cancelled.${NC}"
        exit 0
    fi
fi

# Build arguments
BUILD_ARGS="--build"
if [ "$CLEAN" = true ]; then
    echo -e "${YELLOW}🧹 Clean rebuild requested...${NC}"
    BUILD_ARGS="--build --force-recreate --no-cache"
fi

# Profile arguments
PROFILE_ARGS=""
if [ "$TOOLS" = true ]; then
    echo -e "${YELLOW}🛠️  Launching development tools...${NC}"
    PROFILE_ARGS="--profile tools"
fi

# Start containers
echo -e "${CYAN}🐳 Starting Docker containers...${NC}"
docker-compose up -d $BUILD_ARGS $PROFILE_ARGS

# Wait for health
echo ""
echo -e "${YELLOW}⏳ Waiting for services to be ready...${NC}"
echo -e "   ${NC}This may take 30-60 seconds on first run...${NC}"

MAX_WAIT=120
ELAPSED=0
CHECK_INTERVAL=5

while [ $ELAPSED -lt $MAX_WAIT ]; do
    BACKEND_HEALTH=$(docker inspect --format='{{.State.Health.Status}}' colaflow-api 2>/dev/null || echo "starting")

    if [ "$BACKEND_HEALTH" = "healthy" ]; then
        echo -e "${GREEN}✅ All services are ready!${NC}"
        break
    fi

    sleep $CHECK_INTERVAL
    ELAPSED=$((ELAPSED + CHECK_INTERVAL))
    echo -e "   ${NC}Still waiting... ($ELAPSED/$MAX_WAIT seconds)${NC}"
done

# Run migrations
echo ""
echo -e "${CYAN}🗄️  Running database migrations...${NC}"
docker-compose exec -T backend dotnet ef database update --no-build

# Display info
echo ""
echo -e "${CYAN}=====================================${NC}"
echo -e "${GREEN}✅ ColaFlow Development Environment Ready!${NC}"
echo -e "${CYAN}=====================================${NC}"
echo ""
echo -e "${NC}📍 Service URLs:${NC}"
echo -e "   ${CYAN}Frontend:  http://localhost:3000${NC}"
echo -e "   ${CYAN}Backend:   http://localhost:5000${NC}"
echo -e "   ${CYAN}Swagger:   http://localhost:5000/swagger${NC}"
echo ""
echo -e "${NC}🔐 Demo Credentials:${NC}"
echo -e "   ${CYAN}Email:     owner@demo.com${NC}"
echo -e "   ${CYAN}Password:  Admin123!${NC}"
echo ""

if [ "$TOOLS" = true ]; then
    echo -e "${NC}🛠️  Development Tools:${NC}"
    echo -e "   ${CYAN}pgAdmin:         http://localhost:5050${NC}"
    echo -e "   ${CYAN}Redis Commander: http://localhost:8081${NC}"
    echo ""
fi

echo -e "${NC}📚 Useful Commands:${NC}"
echo -e "   View logs:        ${NC}docker-compose logs -f${NC}"
echo -e "   Stop services:    ${NC}docker-compose down${NC}"
echo -e "   Restart backend:  ${NC}docker-compose restart backend${NC}"
echo ""

if [ "$LOGS" = true ]; then
    echo -e "${YELLOW}📋 Showing logs (Ctrl+C to exit)...${NC}"
    docker-compose logs -f
fi
```

#### 3.5.3 Package.json 快捷命令

在 `colaflow-web/package.json` 中添加：

```json
{
  "scripts": {
    "docker:dev": "cd .. && docker-compose up -d",
    "docker:dev:tools": "cd .. && docker-compose --profile tools up -d",
    "docker:stop": "cd .. && docker-compose down",
    "docker:logs": "cd .. && docker-compose logs -f",
    "docker:restart": "cd .. && docker-compose restart backend frontend",
    "docker:rebuild": "cd .. && docker-compose up -d --build",
    "docker:clean": "cd .. && docker-compose down -v && docker-compose up -d --build"
  }
}
```

---

## 四、开发者工作流

### 4.1 首次启动

```powershell
# Windows
.\scripts\dev-start.ps1

# Linux/Mac
chmod +x scripts/dev-start.sh
./scripts/dev-start.sh
```

**首次启动流程**:
1. 检查 Docker 是否运行
2. 创建 `.env` 文件（如果不存在）
3. 拉取并构建所有镜像（约 5-10 分钟）
4. 启动所有容器
5. 等待健康检查通过
6. 运行 EF Core 迁移
7. 自动插入种子数据
8. 显示访问信息

### 4.2 日常开发

```powershell
# 前端开发者典型工作流

# 1. 启动后端服务
npm run docker:dev

# 2. 前端本地开发（热重载）
cd colaflow-web
npm run dev

# 3. 查看后端日志
npm run docker:logs

# 4. 重启后端（修改配置后）
npm run docker:restart

# 5. 停止所有服务
npm run docker:stop
```

### 4.3 常见场景

#### 场景 1：后端代码变更
```powershell
# 后端代码变更需要重新构建
docker-compose up -d --build backend
```

#### 场景 2：数据库迁移变更
```powershell
# 应用新迁移
docker-compose exec backend dotnet ef database update

# 回滚迁移
docker-compose exec backend dotnet ef database update <previous-migration-name>
```

#### 场景 3：重置开发数据
```powershell
# Windows
.\scripts\dev-start.ps1 -Reset

# Linux/Mac
./scripts/dev-start.sh --reset
```

#### 场景 4：启用开发工具
```powershell
# Windows
.\scripts\dev-start.ps1 -Tools

# Linux/Mac
./scripts/dev-start.sh --tools
```

#### 场景 5：调试后端 API
```powershell
# 查看实时日志
docker-compose logs -f backend

# 进入容器
docker-compose exec backend bash

# 查看数据库连接
docker-compose exec backend dotnet ef dbcontext info
```

### 4.4 前端环境变量配置

创建 `colaflow-web/.env.local`:

```env
# 连接到本地 Docker 容器的后端
NEXT_PUBLIC_API_URL=http://localhost:5000
NEXT_PUBLIC_WS_URL=ws://localhost:5000/hubs/project

# 开发模式设置
NEXT_PUBLIC_ENABLE_DEBUG=true
NEXT_PUBLIC_ENABLE_ANALYTICS=false

# 可选：连接到远程后端
# NEXT_PUBLIC_API_URL=https://dev-api.colaflow.com
```

---

## 五、性能优化

### 5.1 构建缓存优化

| 优化项 | 方法 | 效果 |
|--------|------|------|
| **Docker 层缓存** | 先复制 package.json/csproj | 依赖未变时跳过安装 |
| **多阶段构建** | 分离 build 和 runtime | 减少最终镜像大小 50% |
| **npm ci** | 使用 clean install | 比 npm install 快 2-3x |
| **BuildKit** | 启用 Docker BuildKit | 并行构建，提升 30% |

### 5.2 启用 BuildKit

在 `.env` 中添加：

```env
DOCKER_BUILDKIT=1
COMPOSE_DOCKER_CLI_BUILD=1
```

### 5.3 资源限制

在 `docker-compose.yml` 中添加资源限制：

```yaml
services:
  backend:
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
        reservations:
          cpus: '0.5'
          memory: 512M

  frontend:
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 1G
```

### 5.4 容器启动时间优化

| 服务 | 目标启动时间 | 优化方法 |
|------|--------------|----------|
| PostgreSQL | < 5s | 使用 alpine 镜像 |
| Redis | < 3s | 使用 alpine 镜像 |
| Backend | < 30s | 多阶段构建 + 健康检查 |
| Frontend | < 15s | npm ci + 缓存 node_modules |

---

## 六、故障排查

### 6.1 常见问题

#### 问题 1：容器无法启动

**症状**:
```
Error: Cannot start service backend: ...
```

**解决**:
```powershell
# 查看详细日志
docker-compose logs backend

# 检查端口占用
netstat -ano | findstr :5000

# 强制重建
docker-compose up -d --build --force-recreate
```

#### 问题 2：数据库连接失败

**症状**:
```
Npgsql.NpgsqlException: Connection refused
```

**解决**:
```powershell
# 检查 PostgreSQL 健康状态
docker-compose ps postgres

# 查看 PostgreSQL 日志
docker-compose logs postgres

# 重启 PostgreSQL
docker-compose restart postgres
```

#### 问题 3：前端无法连接后端

**症状**:
```
Failed to fetch: http://localhost:5000/api/...
```

**解决**:
1. 检查 `.env.local` 中的 `NEXT_PUBLIC_API_URL`
2. 确认后端健康检查通过：`docker-compose ps backend`
3. 检查 CORS 配置：`docker-compose logs backend | grep CORS`

#### 问题 4：热重载不工作

**症状**: 修改前端代码后浏览器不自动刷新

**解决**:
```powershell
# 确认 volume 挂载正确
docker-compose config | grep -A 5 "frontend.*volumes"

# 重启前端容器
docker-compose restart frontend
```

### 6.2 诊断命令

```powershell
# 检查所有服务状态
docker-compose ps

# 查看资源使用
docker stats

# 检查网络连接
docker-compose exec backend curl http://postgres:5432

# 查看环境变量
docker-compose exec backend env | grep CONNECTION

# 进入容器调试
docker-compose exec backend bash
docker-compose exec postgres psql -U colaflow
```

---

## 七、安全考虑

### 7.1 开发环境安全清单

| 检查项 | 状态 | 说明 |
|--------|------|------|
| ✅ 使用 `.env` 文件 | 推荐 | 不提交到 Git |
| ✅ 强密码策略 | 推荐 | 生产环境必须更改 |
| ⚠️ 暴露端口 | 注意 | 仅开发环境，生产环境需修改 |
| ⚠️ CORS 宽松配置 | 注意 | 仅开发环境，生产环境需限制 |
| ❌ 使用 root 用户 | 禁止 | 前端已使用非 root 用户 |

### 7.2 .gitignore 配置

确保以下文件不被提交：

```gitignore
# Environment variables
.env
.env.local

# Docker volumes (if using bind mounts)
.data/
postgres_data/
redis_data/

# Development certificates
*.pfx
*.pem
```

---

## 八、CI/CD 集成

### 8.1 GitHub Actions 示例

```yaml
name: Docker Build Test

on:
  pull_request:
    branches: [ main, develop ]

jobs:
  docker-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Build backend image
        run: |
          docker build -t colaflow-api:test ./colaflow-api

      - name: Build frontend image
        run: |
          docker build -t colaflow-web:test ./colaflow-web --target development

      - name: Test docker-compose
        run: |
          docker-compose up -d
          sleep 30
          docker-compose ps
          docker-compose logs
          docker-compose down
```

---

## 九、下一步计划

### 9.1 实施优先级

| 任务 | 优先级 | 估时 | 负责人 |
|------|--------|------|--------|
| 1. 修复后端 Dockerfile | 🔴 P0 | 1h | Backend |
| 2. 创建前端 Dockerfile | 🔴 P0 | 2h | Frontend |
| 3. 创建数据库脚本 | 🟡 P1 | 2h | Backend |
| 4. 创建启动脚本 | 🟡 P1 | 2h | DevOps |
| 5. 编写开发者文档 | 🟢 P2 | 3h | PM |
| 6. 性能测试和优化 | 🟢 P2 | 4h | QA |

### 9.2 验收标准

- [ ] 前端开发者可以在 **5 分钟内**启动完整后端环境
- [ ] 首次启动时间 < **60 秒**（包含构建）
- [ ] 后续启动时间 < **30 秒**
- [ ] 前端热重载工作正常
- [ ] 种子数据自动加载
- [ ] 所有服务健康检查通过
- [ ] 文档完整且易于理解
- [ ] 支持 Windows、Linux、macOS

---

## 十、参考资料

### 10.1 官方文档

- [Docker Compose Documentation](https://docs.docker.com/compose/)
- [.NET Docker Images](https://hub.docker.com/_/microsoft-dotnet)
- [PostgreSQL Docker Image](https://hub.docker.com/_/postgres)
- [Redis Docker Image](https://hub.docker.com/_/redis)
- [Next.js Docker Deployment](https://nextjs.org/docs/deployment#docker-image)

### 10.2 最佳实践

- [Docker Multi-Stage Builds](https://docs.docker.com/build/building/multi-stage/)
- [Docker BuildKit](https://docs.docker.com/build/buildkit/)
- [.NET Container Best Practices](https://learn.microsoft.com/en-us/dotnet/core/docker/build-container)
- [Next.js with Docker](https://github.com/vercel/next.js/tree/canary/examples/with-docker)

---

## 附录

### A. 完整文件清单

实施本方案需要创建/修改以下文件：

```
product-master/
├── colaflow-api/
│   └── Dockerfile (需修改)
├── colaflow-web/
│   ├── Dockerfile (需创建)
│   ├── .dockerignore (需创建)
│   ├── .env.local.example (需创建)
│   └── next.config.ts (需修改)
├── scripts/
│   ├── init-db.sql (需创建)
│   ├── seed-data.sql (需创建)
│   ├── dev-start.ps1 (需创建)
│   └── dev-start.sh (需创建)
├── docker-compose.yml (需修改)
├── docker-compose.override.yml (可选修改)
├── .env.example (需创建)
├── .dockerignore (需创建)
└── docs/
    ├── DOCKER-DEVELOPMENT-ENVIRONMENT.md (本文档)
    └── DOCKER-QUICKSTART.md (需创建，简化版)
```

### B. 估时总结

| 阶段 | 任务 | 估时 |
|------|------|------|
| **Phase 1** | 后端 Dockerfile 修复 | 1h |
| **Phase 2** | 前端 Dockerfile 创建 | 2h |
| **Phase 3** | 数据库脚本编写 | 2h |
| **Phase 4** | 启动脚本开发 | 2h |
| **Phase 5** | 文档编写 | 3h |
| **Phase 6** | 测试和调试 | 4h |
| **总计** | | **14h** |

---

**文档版本**: 1.0
**最后更新**: 2025-11-04
**维护者**: ColaFlow Architecture Team
