38 KiB
38 KiB
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 多阶段构建策略
# 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 多阶段构建
# 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 输出:
const nextConfig: NextConfig = {
// 生产环境使用 standalone 模式
output: process.env.NODE_ENV === 'production' ? 'standalone' : undefined,
// 其他配置...
};
3.3 Docker Compose 优化
3.3.1 完整的 docker-compose.yml
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 文件:
# 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)
-- 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)
-- 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)
#!/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)
#!/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 中添加:
{
"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 首次启动
# Windows
.\scripts\dev-start.ps1
# Linux/Mac
chmod +x scripts/dev-start.sh
./scripts/dev-start.sh
首次启动流程:
- 检查 Docker 是否运行
- 创建
.env文件(如果不存在) - 拉取并构建所有镜像(约 5-10 分钟)
- 启动所有容器
- 等待健康检查通过
- 运行 EF Core 迁移
- 自动插入种子数据
- 显示访问信息
4.2 日常开发
# 前端开发者典型工作流
# 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:后端代码变更
# 后端代码变更需要重新构建
docker-compose up -d --build backend
场景 2:数据库迁移变更
# 应用新迁移
docker-compose exec backend dotnet ef database update
# 回滚迁移
docker-compose exec backend dotnet ef database update <previous-migration-name>
场景 3:重置开发数据
# Windows
.\scripts\dev-start.ps1 -Reset
# Linux/Mac
./scripts/dev-start.sh --reset
场景 4:启用开发工具
# Windows
.\scripts\dev-start.ps1 -Tools
# Linux/Mac
./scripts/dev-start.sh --tools
场景 5:调试后端 API
# 查看实时日志
docker-compose logs -f backend
# 进入容器
docker-compose exec backend bash
# 查看数据库连接
docker-compose exec backend dotnet ef dbcontext info
4.4 前端环境变量配置
创建 colaflow-web/.env.local:
# 连接到本地 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 中添加:
DOCKER_BUILDKIT=1
COMPOSE_DOCKER_CLI_BUILD=1
5.3 资源限制
在 docker-compose.yml 中添加资源限制:
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: ...
解决:
# 查看详细日志
docker-compose logs backend
# 检查端口占用
netstat -ano | findstr :5000
# 强制重建
docker-compose up -d --build --force-recreate
问题 2:数据库连接失败
症状:
Npgsql.NpgsqlException: Connection refused
解决:
# 检查 PostgreSQL 健康状态
docker-compose ps postgres
# 查看 PostgreSQL 日志
docker-compose logs postgres
# 重启 PostgreSQL
docker-compose restart postgres
问题 3:前端无法连接后端
症状:
Failed to fetch: http://localhost:5000/api/...
解决:
- 检查
.env.local中的NEXT_PUBLIC_API_URL - 确认后端健康检查通过:
docker-compose ps backend - 检查 CORS 配置:
docker-compose logs backend | grep CORS
问题 4:热重载不工作
症状: 修改前端代码后浏览器不自动刷新
解决:
# 确认 volume 挂载正确
docker-compose config | grep -A 5 "frontend.*volumes"
# 重启前端容器
docker-compose restart frontend
6.2 诊断命令
# 检查所有服务状态
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 配置
确保以下文件不被提交:
# 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 示例
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
- .NET Docker Images
- PostgreSQL Docker Image
- Redis Docker Image
- Next.js Docker Deployment
10.2 最佳实践
附录
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