nkds

导航

 

MonkeyCode企业级内网部署完全手册:从零到生产(2026实战版)

"对于金融、政府、军工等安全敏感行业来说,'数据不出内网'不是可选项——而是硬性要求。MonkeyCode开源版的价值正在于此:它让你在内网隔离环境中也能拥有世界级的AI编程能力" —— 本文提供一份完整的企业级内网部署指南,涵盖从环境准备到生产运维的全流程。


一、为什么需要内网部署?

🔒 内网部署的必要性分析

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

必须内网部署的行业和场景:

┌─────────────────────────────────────────────┐
│ 🏦 金融行业(银行/证券/保险/支付)          │
│ → 监管要求:等保三级、PCI-DSS             │
│ → 数据合规:客户数据禁止出境              │
│ → 审计要求:所有操作可追溯                │
├─────────────────────────────────────────────┤
│ 🏛️ 政府/军工/央企                         │
│ → 涉密信息系统分级保护                    │
│ → 信创国产化要求                          │
│ → 与互联网物理隔离                        │
├─────────────────────────────────────────────┤
│ 🏥 医疗健康(医院/药企/医保)              │
│ → HIPAA/GDPR等隐私法规                   │
│ → 患者数据绝对保密                        │
│ → 医疗器械软件认证                        │
├─────────────────────────────────────────────┤
│ 🔬 科研院所(国防科研/前沿技术)           │
│ → 知识产权保护                            │
│ → 研究数据防泄露                          │
│ → 专有算法不外泄                          │
├─────────────────────────────────────────────┤
│ 🏭 大型制造业(汽车/航空/能源)            │
│ → 工业控制系统安全                       │
│ → 供应链知识产权保护                      │
│ → 内部研发资产防护                        │
└─────────────────────────────────────────────┘

内网部署 vs 云端使用对比:

维度              云端版          开源内网版
──────────────────────────────────────────────
数据位置          云端服务器      本地机房 ✅
网络要求          需要外网        完全离线可用 ✅
数据主权          供应商持有      自己掌控 ✅
合规审计          依赖供应商报告  自主可控 ✅
定制能力          受限            完全自由 ✅
成本模式          按用量付费      一次性投入 ✅
运维复杂度        低(托管)      中高(自维护)
功能完整性        100%            100%(同源码)

二、部署前准备

2.1 硬件需求评估

💻 硬件配置参考表

团队规模    推荐配置                    CPU   内存    硬盘     带宽
─────────────────────────────────────────────────────────────
1-10人     最小可用                  4核   8G     50G SSD  不需要
10-30人    推荐配置                  8核   16G    200G SSD 不需要
30-100人   标准生产                 16核  32G    500G SSD 局域网
100-500人  高性能配置               32核  64G    1T SSD   千兆+
500人+     集群部署(见下文K8s方案) 多节点  多节点   共享存储 万兆

详细说明:

CPU:
→ 主要消耗在LLM API转发和代码分析上
→ AI模型推理不在本地(调用外部API),CPU压力不大
→ 推荐:Intel Xeon Gold 或 AMD EPYC 系列

内存:
→ PostgreSQL + Redis + 后端服务 占主要内存
→ 规则:每并发用户预留 512MB - 1GB
→ 示例:50人团队 → 32GB 足够

硬盘:
→ 代码仓库缓存:按项目数量估算(通常 10-50GB)
→ 扫描历史记录:建议保留3个月(20-100GB)
→ 日志文件:开启日志轮转后约 5-20GB
→ 总计:SSD 200GB 起,推荐 500GB+

网络:
→ 内网部署不需要公网IP
→ 但需要能够访问LLM Provider API(或本地模型)
→ 如果完全离线:需要额外部署本地大模型(见第七节)

💡 成本估算(一次性硬件投入):
30人团队标准配置 ≈ ¥3-5万(服务器+存储+网络设备)
对比云端方案年费 ≈ ¥5-10万/年
→ 内网部署第1年即可回本!

2.2 软件依赖清单

📦 必需软件清单

操作系统(选一):
├── Ubuntu Server 22.04 LTS / 24.04 LTS  ← 推荐
├── CentOS Stream 9 / Rocky Linux 9
├── Debian 12 (Bookworm)
└── Red Hat Enterprise Linux 9(需订阅)

运行时环境:
├── Python 3.11+ (后端核心服务)
├── Node.js 18+ LTS (前端构建)
├── PostgreSQL 15+ (主数据库)
├── Redis 7+ (缓存/队列)
├── Git 2.40+ (版本控制集成)
└── Docker & Docker Compose(可选,容器化部署)

开发工具(可选但推荐):
├── GitLab CE / Gitea (代码托管)
├── Jenkins / GitLab CI (CI/CD集成)
├── Prometheus + Grafana (监控告警)
└── ELK Stack / Loki (日志收集)

LLM Provider(至少选一个):
├── DeepSeek API ← 性价比最高(推荐)
├── 通义千问 Qwen API ← 国内访问快
├── 智谱AI GLM API ← 国产可靠
├── 百度文心一言 ERNIE API
├── 本地部署模型(完全离线方案)
│   ├── Qwen2.5-Coder-7B-Instruct
│   ├── DeepSeek-Coder-V2-Lite
│   └── CodeLlama-70B(需要强GPU)

三、快速部署(Docker Compose方式)

# docker-compose.production.yaml — 生产级Docker编排

version: '3.8'

services:
  # ════════════════════════════════
  # PostgreSQL 数据库
  # ════════════════════════════════
  postgres:
    image: postgres:15-alpine
    container_name: mc-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: monkeycode
      POSTGRES_USER: ${DB_USER:-mc_admin}
      POSTGRES_PASSWORD: ${DB_PASSWORD:-CHANGE_ME_IN_PRODUCTION}
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - pg_data:/var/lib/postgresql/data
      - ./init-db:/docker-entrypoint-initdb.d:ro
    ports:
      - "127.0.0.1:5432:5432"  # 仅本地绑定
    command:
      - "postgres"
      - "-c"
      - "max_connections=200"
      - "-c"
      - "shared_buffers=256MB"
      - "-c"
      - "effective_cache_size=768MB"
      - "-c"
      - "maintenance_work_mem=64MB"
      - "-c"
      - "wal_level=replica"
      - "-c"
      - "max_wal_senders=3"
      - "-c"
      - "hot_standby=on"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mc_admin -d monkeycode"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    networks:
      - mc-backend
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"

  # ════════════════════════════════
  # Redis 缓存
  # ════════════════════════════════
  redis:
    image: redis:7-alpine
    container_name: mc-redis
    restart: unless-stopped
    command: >
      redis-server 
      --requirepass ${REDIS_PASSWORD:-CHANGE_ME}
      --maxmemory 512mb
      --maxmemory-policy allkeys-lru
      --appendonly yes
      --appendfsync everysec
      --save 60 1000
      --save 300 100
    volumes:
      - redis_data:/data
    ports:
      - "127.0.0.1:6379:6379"  # 仅本地绑定
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-CHANGE_ME}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - mc-backend
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "3"

  # ════════════════════════════════
  # MonkeyCode API 服务
  # ════════════════════════════════
  monkeycode-api:
    build:
      context: .
      dockerfile: Dockerfile.api
      args:
        PYTHON_VERSION: "3.11"
    image: monkeycode-api:latest
    container_name: mc-api
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      # 数据库连接
      DATABASE_URL: postgresql://mc_admin:${DB_PASSWORD:-CHANGE_ME}@postgres:5432/monkeycode
      
      # Redis连接
      REDIS_URL: redis://:${REDIS_PASSWORD:-CHANGE_ME}@redis:6379/0
      
      # LLM Provider 配置
      LLM_PROVIDER: ${LLM_PROVIDER:-deepseek}
      DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY}
      QWEN_API_KEY: ${QWEN_API_KEY}
      GLM_API_KEY: ${GLM_API_KEY}
      
      # 应用配置
      SECRET_KEY: ${SECRET_KEY:-generate-random-here}
      ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-http://localhost:3000}
      LOG_LEVEL: ${LOG_LEVEL:-INFO}
      
      # 安全配置
      ENABLE_AUTH: "true"
      AUTH_METHOD: ${AUTH_METHOD:-ldap}  # ldap/oauth2/token
      LDAP_URL: ${LDAP_URL:-ldap://your-ldap-server:389}
      LDAP_BASE_DN: ${LDAP_BASE_DN:-dc=company,dc=com}
      LDAP_BIND_USER: ${LDAP_BIND_USER}
      LDAP_BIND_PASSWORD: ${LDAP_BIND_PASSWORD}
      
      # SDD默认配置
      SDD_DEFAULT_PATH: /app/config/default.sdd.yaml
      
      # MonkeyScan配置
      MONKEYSCAN_ENABLED: "true"
      MONKEYSCAN_BLOCK_ON_CRITICAL: "true"
      
      # Worker配置
      WORKER_CONCURRENCY: ${WORKER_CONCURRENCY:-4}
      TASK_TIMEOUT: ${TASK_TIMEOUT:-1800}  # 30分钟超时
    ports:
      - "8000:8000"
    volumes:
      - ./config:/app/config:ro       # 只读挂载配置
      - workspace_data:/app/workspace # 工作区数据
      - scan_reports:/app/reports    # 扫描报告
      - logs:/app/logs               # 日志目录
    networks:
      - mc-backend
      - mc-frontend
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 4G
        reservations:
          cpus: '2.0'
          memory: 2G
    logging:
      driver: json-file
      options:
        max-size: "100m"
        max-file: "5"

  # ════════════════════════════════
  # MonkeyCode Web 前端
  # ════════════════════════════════
  monkeycode-web:
    build:
      context: .
      dockerfile: Dockerfile.web
      args:
        NODE_ENV: production
        VITE_API_BASE_URL: http://${HOST_IP:-localhost}:8000
    image: monkeycode-web:latest
    container_name: mc-web
    restart: unless-stopped
    depends_on:
      - monkeycode-api
    ports:
      - "3000:80"  # Nginx在容器内监听80
    networks:
      - mc-frontend
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "3"

  # ════════════════════════════════
  # Nginx 反向代理(可选,用于生产环境)
  # ════════════════════════════════
  nginx:
    image: nginx:alpine
    container_name: mc-nginx
    restart: unless-stopped
    depends_on:
      - monkeycode-api
      - monkeycode-web
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/certs:/etc/nginx/certs:ro  # SSL证书
      - nginx_logs:/var/log/nginx
    networks:
      - mc-frontend
      - mc-backend
    logging:
      driver: json-file
      options:
        max-size: "20m"
        max-file: "3"

# ════════════════════════════════════
# 数据卷定义
# ════════════════════════════════════
volumes:
  pg_data:
    driver: local
  redis_data:
    driver: local
  workspace_data:
    driver: local
  scan_reports:
    driver: local
  logs:
    driver: local
  nginx_logs:
    driver: local

# ════════════════════════════════════
# 网络定义
# ════════════════════════════════════
networks:
  mc-backend:
    driver: bridge
    internal: true  # 内部网络,不暴露到宿主机
  mc-frontend:
    driver: bridge

四、Nginx反向代理与SSL配置

# nginx/nginx.conf — 生产级Nginx配置

# 全局设置
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 2048;
    use epoll;
    multi_accept on;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time';

    access_log /var/log/nginx/access.log main;
    error_log  /var/log/nginx/error.log warn;

    # 基础优化
    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Gzip压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json application/javascript
               application/xml application/rss+xml image/svg+xml;

    # 安全头
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;

    # 上传大小限制(代码文件可能较大)
    client_max_body_size 50m;

    # 速率限制
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s;
    limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;

    # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    # HTTP → HTTPS 重定向
    # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    server {
        listen 80;
        server_name monkeycode.yourcompany.com;
        
        # ACME证书挑战(Let's Encrypt)
        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }
        
        # 其他请求重定向到HTTPS
        location / {
            return 301 https://$server_name$request_uri;
        }
    }

    # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    # HTTPS 主站配置
    # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    server {
        listen 443 ssl http2;
        server_name monkeycode.yourcompany.com;

        # SSL证书配置
        ssl_certificate     /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
        ssl_prefer_server_ciphers off;
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_session_tickets off;

        # HSTS(严格传输安全)
        add_header Strict-Transport-Security "max-age=63072000" always;

        # 前端静态资源
        location / {
            proxy_pass http://monkeycode-web:80;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            # WebSocket支持(实时通知)
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }

        # API代理
        location /api/ {
            limit_req zone=api_limit burst=50 nodelay;
            
            proxy_pass http://monkeycode-api:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            # API超时设置(长时间任务)
            proxy_connect_timeout 60s;
            proxy_read_timeout 1800s;  # 30分钟(Agent任务可能很长)
            proxy_send_timeout 60s;
            
            # 缓冲设置
            proxy_buffering off;  # 流式响应
        }

        # 登录接口特殊限制(防暴力破解)
        location = /api/auth/login {
            limit_req zone=login_limit burst=3 nodelay;
            
            proxy_pass http://monkeycode-api:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # 健康检查端点(无需认证)
        location /health {
            proxy_pass http://monkeycode-api:8000;
            access_log off;
        }

        # 静态资源缓存
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
            expires 30d;
            add_header Cache-Control "public, immutable";
            proxy_pass http->monkeycode-web:80;
        }

        # 禁止访问隐藏文件
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
    }
}

五、LDAP/AD域认证集成

# config/auth_ldap.py — LDAP认证配置示例

"""
MonkeyCode LDAP/Active Directory 认证集成

支持两种模式:
1. LDAP Simple Bind(简单绑定)
2. Active Directory Kerberos认证(高级安全)
"""

import os
from dataclasses import dataclass
from typing import Optional, List


@dataclass
class LDAPConfig:
    """LDAP配置"""
    server_url: str           # ldap://ad.company.com:389
    base_dn: str              # dc=company,dc=com
    bind_user: str            # cn=admin,dc=company,dc=com
    bind_password: str
    user_search_base: str     # ou=Users,dc=company,dc=com
    group_search_base: str    # ou=Groups,dc=company,dc=com
    
    # 用户属性映射
    username_attr: str = "sAMAccountName"  # AD用sAMAccountName
    email_attr: str = "mail"
    display_name_attr: str = "displayName"
    
    # 组权限映射
    admin_group_dn: Optional[str] = None   # cn=MC-Admins,ou=Groups,...
    developer_group_dn: Optional[str] = None
    viewer_group_dn: Optional[str] = None
    
    # 安全选项
    use_ssl: bool = True
    cert_path: Optional[str] = None


# 默认配置模板
DEFAULT_LDAP_CONFIG = LDAPConfig(
    server_url=os.getenv("LDAP_URL", "ldap://ad.company.com:389"),
    base_dn=os.getenv("LDAP_BASE_DN", "dc=company,dc=com"),
    bind_user=os.getenv("LDAP_BIND_USER", ""),
    bind_password=os.getenv("LDAP_BIND_PASSWORD", ""),
    user_search_base=os.getenv("LDAP_USER_BASE", "ou=Developers,dc=company,dc=com"),
    group_search_base=os.getenv("LDAP_GROUP_BASE", "ou=Groups,dc=company,dc=com"),
    admin_group_dn="cn=MonkeyCode-Admins,ou=Groups,dc=company,dc=com",
    developer_group_dn="cn=MonkeyCode-Users,ou=Groups,dc=company,dc=com",
    viewer_group_dn="cn=MonkeyCode-Viewers,ou=Groups,dc=company,dc=com",
    use_ssl=True,
)


# 使用说明:
# 1. 在 .env 文件中配置LDAP连接信息
# 2. 确保MonkeyCode服务器能访问LDAP服务器端口(389/636)
# 3. 在AD中创建对应的用户组
# 4. 将用户分配到对应组以获得相应权限

# 权限体系:
# MC-Admins组  → 管理员(全部权限 + 系统管理)
# MC-Users组   → 普通开发者(使用AI编程 + 查看自己的项目)
# MC-Viewers组 → 只读用户(仅查看扫描报告和统计)

六、备份与灾难恢复

#!/bin/bash
# scripts/backup.sh — 自动化备份脚本

set -euo pipefail

# ═════════════════════════════════════════
# MonkeyCode 企业级备份脚本
# 建议:通过cron每天凌晨2点执行
# crontab: 0 2 * * * /opt/monkeycode/scripts/backup.sh
# ═════════════════════════════════════════

CONFIG_DIR="/opt/monkeycode/config"
BACKUP_ROOT="/opt/monkeycode/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="${BACKUP_ROOT}/${DATE}"
RETENTION_DAYS=30  # 保留30天备份

echo "[${DATE}] 开始备份..."

# 创建备份目录
mkdir -p "${BACKUP_DIR}/{db,config,workspace,reports}"

# ═════════════════════════════════════════
# 1. PostgreSQL 数据库备份
# ═════════════════════════════════════════
echo ">>> 备份数据库..."
docker exec mc-postgres pg_dump \
    -U mc_admin \
    -F c \
    -f "/backups/db/monkeycode_${DATE}.dump" \
    monkeycode

echo "    数据库备份完成: $(du -h ${BACKUP_DIR}/db/*.dump | cut -f1)"

# ═════════════════════════════════════════
# 2. 配置文件备份
# ═════════════════════════════════════════
echo ">>> 备份配置文件..."
cp -r "${CONFIG_DIR}/" "${BACKUP_DIR}/config/"
# 敏感信息脱敏(移除真实密码)
find "${BACKUP_DIR}/config" -name ".env" -exec sed -i 's/PASSWORD=.*/PASSWORD=**REDACTED**/' {} \;

echo "    配置文件备份完成"

# ═════════════════════════════════════════
# 3. 工作区数据备份(增量)
# ═════════════════════════════════════════
echo ">>> 备份工作区数据..."
docker cp mc-api:/app/workspace "${BACKUP_DIR}/workspace/"

echo "    工作区备份完成: $(du -sh ${BACKUP_DIR}/workspace | cut -f1)"

# ═════════════════════════════════════════
# 4. 扫描报告备份
# ═════════════════════════════════════════
echo ">>> 备份扫描报告..."
docker cp mc-api:/app/reports "${BACKUP_DIR}/reports/"

echo "    报告备份完成: $(du -sh ${BACKUP_DIR}/reports | cut -f1)"

# ═════════════════════════════════════════
# 5. 压缩打包
# ═════════════════════════════════════════
echo ">>> 压缩备份..."
tar -czf "${BACKUP_ROOT}/monkeycode_backup_${DATE}.tar.gz" \
    -C "${BACKUP_ROOT}" "${DATE}"

# 清理未压缩目录
rm -rf "${BACKUP_DIR}"

BACKUP_SIZE=$(du -h "${BACKUP_ROOT}/monkeycode_backup_${DATE}.tar.gz" | cut -f1)
echo "    备份包大小: ${BACKUP_SIZE}"

# ═════════════════════════════════════════
# 6. 清理过期备份
# ═════════════════════════════════════════
echo ">>> 清理${RETENTION_DAYS}天前的旧备份..."
find "${BACKUP_ROOT}" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete

TOTAL_SIZE=$(du -sh ${BACKUP_ROOT} | cut -f1)
echo "    备份总占用空间: ${TOTAL_SIZE}"

# ═════════════════════════════════════════
# 7. 备份验证(可选)
# ═════════════════════════════════════════
echo ">>> 验证备份完整性..."
if tar -tzf "${BACKUP_ROOT}/monkeycode_backup_${DATE}.tar.gz" >/dev/null 2>&1; then
    echo "    ✅ 备份验证通过"
else
    echo "    ❌ 备份损坏!请检查磁盘空间"
    exit 1
fi

echo "[${DATE}] 备份完成!✅"
echo "备份文件: ${BACKUP_ROOT}/monkeycode_backup_${DATE}.tar.gz"

七、完全离线方案(本地大模型部署)

🔒 完全离线部署架构图

当企业网络无法访问任何外部API时,
需要在内部部署本地大语言模型。

┌─────────────────────────────────────────────────────┐
│              完全离线架构                             │
│                                                     │
│  ┌──────────┐                                       │
│  │ GPU服务器 │  ← 需要 NVIDIA A100/H100 或等效GPU    │
│  │ (推理节点)│                                        │
│  └────┬─────┘                                       │
│       │ vLLM / TGI 推理引擎                         │
│       │                                             │
│  ┌────▼──────────────────────────────────────┐      │
│  │         本地模型选择                        │      │
│  ├─────────────────────────────────────────────┤      │
│  │ 模型              │ 显存需求 │ 推荐GPU        │      │
│  ├──────────────────┼─────────┼───────────────┤      │
│  │ Qwen2.5-Coder-7B  │ 16GB    │ RTX 4090/A5000│      │
│  │ Qwen2.5-Coder-32B │ 72GB    │ A100 80GB×1   │      │
│  │ DeepSeek-V2-Lite  │ 48GB    │ A6000×2       │      │
│  │ CodeLlama-70B     │ 140GB   │ A100 80GB×2   │      │
│  │ Qwen2.5-Coder-72B │ 144GB   │ H100 80GB×2   │      │
│  └─────────────────────────────────────────────┘      │
│                                                     │
│  MonkeyCode配置修改:                                │
│  LLM_PROVIDER=vllm                                  │
│  VLLM_ENDPOINT=http://gpu-server:8000/v1            │
│                                                     │
│  所有数据流:                                        │
│  用户 → MonkeyCode → 本地模型 → 结果               │
│  ↑ 全程不出内网 ↑                                   │
└─────────────────────────────────────────────────────┘

vLLM部署命令示例(Qwen2.5-Coder-7B):

# 在GPU服务器上执行
pip install vllm

# 启动推理服务
python -m vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-Coder-7B-Instruct \
    --tensor-parallel-size 1 \
    --max-model-len 32768 \
    --gpu-memory-utilization 0.9 \
    --port 8000 \
    --host 0.0.0.0

# MonkeyCode .env 配置
LLM_PROVIDER=openai-compatible
OPENAI_API_BASE_URL=http://gpu-server:8000/v1
OPENAI_API_KEY=not-needed-for-local

💡 性能参考(单卡A100):
Qwen2.5-Coder-7B:
→ 首token延迟: <1秒
→ 生成速度: 50-80 tokens/s
→ 并发支持: 4-8个同时请求
→ 代码质量: 接近GPT-4水平(编码任务)

足够支撑20-50人的团队日常使用!

八、监控与运维

📊 运维监控体系

关键监控指标:

┌──────────────────────────────────────────────────┐
│ 类别       │ 指标              │ 告警阈值       │
├────────────┼───────────────────┼────────────────┤
│ 可用性     │ 服务健康状态      │ != UP 时告警   │
│            │ HTTP响应时间(P99)  │ > 5s 告警      │
│            │ 错误率(5xx)       │ > 1% 告警      │
├────────────┼───────────────────┼────────────────┤
│ 性能       │ API QPS           │ > 1000 时关注  │
│            │ Agent任务排队长度  │ > 10 告警      │
│            │ LLM响应延迟(P95)  │ > 30s 告警     │
│            │ 数据库查询时间P99  │ > 500ms 告警   │
├────────────┼───────────────────┼────────────────┤
│ 资源       │ CPU使用率         │ > 85% 告警     │
│            │ 内存使用率         │ > 90% 告警     │
│            │ 磁盘使用率         │ > 85% 告警     │
│            │ Redis内存使用率    │ > 80% 告警     │
├────────────┼───────────────────┼────────────────┤
│ 业务       │ 日活用户数(DAU)    │ 异常下降告警   │
│            │ Agent任务成功率    │ < 95% 告警     │
│            │ 安全漏洞发现数     │ Critical>0告警│
│            │ Token日消耗量      │ 异常激增告警   │
└────────────┴───────────────────┴────────────────┘

推荐监控栈:
Prometheus(指标采集)+ Grafana(可视化展示)
+ AlertManager(告警通知)
+ PagerDuty/钉钉/企微(告警通道)

九、常见问题排查

🔧 故障排查速查表

问题1:服务启动失败,报数据库连接错误
→ 检查PostgreSQL是否正常运行:docker ps | grep postgres
→ 检查连接字符串是否正确:用户名/密码/主机名
→ 检查防火墙是否放行5432端口(容器间通信)
→ 查看日志:docker logs mc-postgres

问题2:前端页面加载空白
→ 检查API服务是否启动:curl localhost:8000/health
→ 检查CORS配置:ALLOWED_ORIGINS是否包含前端地址
→ 检查Nginx配置:proxy_pass目标是否正确
→ 浏览器F12查看Console错误信息

问题3:AI功能无响应或报错
→ 检查LLM API Key是否正确配置
→ 测试API连通性:curl -X POST {provider_url}/chat/completions
→ 检查Token余额(DeepSeek/通义等平台控制台)
→ 查看API调用日志:docker logs mc-api | grep llm

问题4:MonkeyScan扫描结果全为空
→ 检查MONKEYSCAN_ENABLED=true是否设置
→ 确认.sdd.yaml中的security_rules配置存在
→ 检查扫描器规则文件是否加载成功
→ 手动触发一次扫描测试

问题5:LDAP认证失败
→ 测试LDAP连通性:ldapsearch -x -H ldap://server:389
→ 检查bind_user是否有足够的搜索权限
→ 确认base_dn和user_search_base路径正确
→ 检查SSL证书(如果use_ssl=true)

问题6:性能随时间下降
→ 检查PostgreSQL表是否需要VACUUM ANALYZE
→ 检查Redis内存是否达到上限
→ 查看工作区目录大小(可能需要清理)
→ 检查Docker容器日志大小

十、部署检查清单

✅ 生产部署最终检查清单

□ 环境准备
  □ 操作系统已更新至最新补丁
  □ Docker和Docker Compose已安装
  □ 防火墙规则已配置(仅开放必要端口)
  □ DNS解析已配置(如使用域名)
  □ SSL证书已获取并部署

□ 安全加固
  □ 所有密码已从默认值更改
  □ .env文件权限设为600
  □ LDAP/AD认证已配置并测试
  □ HTTPS已启用
  □ 安全头已配置(Nginx)
  □ 数据库仅允许本地访问

□ 功能验证
  □ 用户登录/登出正常
  □ AI代码生成功能正常
  □ SDD规范加载正常
  □ MonkeyScan扫描正常
  □ Git集成正常
  □ Agent任务执行正常

□ 高可用(可选)
  □ PostgreSQL主从复制已配置
  □ Redis持久化(AOF)已启用
  □ Docker重启策略为unless-stopped
  □ 定期备份脚本已配置cron
  □ 监控告警已配置

□ 文档移交
  □ 架构拓扑图已绘制
  □ 管理员账号信息已记录
  □ 备份恢复步骤已文档化
  □ 应急联系人列表已建立
  □ 运维手册已编写完成

📌 总结

MonkeyCode的内网部署并不复杂——它本质上是一个标准的Python Web应用加上一些AI相关的组件。Docker Compose方式可以在30分钟内完成基础部署,而Kubernetes集群方案则可以支撑千人规模的团队。最关键的是:一旦部署完成,你的团队就拥有了一个与世界级AI编程能力完全对等的、数据完全自主可控的研发工具。而且这一切,基于AGPL-3.0协议永久免费。


🔗 系列导航


本文为MonkeyCode开源系列第5篇,基于实际生产环境部署经验撰写。

posted on 2026-07-08 16:28  MonkeyCode  阅读(44)  评论(0)    收藏  举报