Files
ColaFlow/docs/DOCKER-DEVELOPMENT-ENVIRONMENT.md
Yaojia Wang 08b317e789
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Add trace files.
2025-11-04 23:28:56 +01:00

1350 lines
38 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 秒**
- [ ] 前端热重载工作正常
- [ ] 种子数据自动加载
- [ ] 所有服务健康检查通过
- [ ] 文档完整且易于理解
- [ ] 支持 WindowsLinuxmacOS
---
## 十、参考资料
### 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