# 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 ``` #### 场景 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