From bfba6dc52fb749fe02223dc6d232a223ccb7659a Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Mon, 11 May 2026 11:59:37 +0800 Subject: [PATCH] feat: add fastgpt framework (v4.14.9) --- frameworks/fastgpt/4.14.9/Dockerfile | 108 +++++++++++++++++++ frameworks/fastgpt/4.14.9/README.md | 152 +++++++++++++++++++++++++++ frameworks/fastgpt/4.14.9/build.conf | 4 + frameworks/fastgpt/4.14.9/test.sh | 59 +++++++++++ 4 files changed, 323 insertions(+) create mode 100644 frameworks/fastgpt/4.14.9/Dockerfile create mode 100644 frameworks/fastgpt/4.14.9/README.md create mode 100644 frameworks/fastgpt/4.14.9/build.conf create mode 100755 frameworks/fastgpt/4.14.9/test.sh diff --git a/frameworks/fastgpt/4.14.9/Dockerfile b/frameworks/fastgpt/4.14.9/Dockerfile new file mode 100644 index 00000000..5625be00 --- /dev/null +++ b/frameworks/fastgpt/4.14.9/Dockerfile @@ -0,0 +1,108 @@ +# ========== Stage 1: Builder ========== +FROM opencloudos/opencloudos9-minimal:latest AS builder + +LABEL maintainer="OpenCloudOS Community" +LABEL org.opencontainers.image.source="https://gitee.com/OpenCloudOS/ai-agent-container" +LABEL org.opencontainers.image.description="FastGPT on OpenCloudOS 9 (builder)" + +# Install system dependencies +RUN dnf install -y \ + git \ + curl \ + ca-certificates \ + xz \ + && dnf clean all \ + && rm -rf /var/cache/yum/* + +# Install Node.js 20.x LTS +# Use official binary tarball (NodeSource RPM repo only has 20.5.1, Next.js needs >=20.9.0) +RUN NODE_VERSION="20.20.2" \ + && ARCH=$(uname -m) \ + && case "$ARCH" in aarch64) ARCH="arm64" ;; x86_64) ARCH="x64" ;; esac \ + && curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${ARCH}.tar.xz" \ + -o /tmp/node.tar.xz \ + && tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 \ + && rm -f /tmp/node.tar.xz + +# Install pnpm 9.x +RUN npm install -g pnpm@9 + +# Clone FastGPT v4.14.9 source code +WORKDIR /build +RUN git clone --depth 1 --branch v4.14.9 https://github.com/labring/FastGPT.git . + +# Install dependencies +RUN pnpm install --frozen-lockfile || pnpm install + +# Build the application +ENV NODE_OPTIONS="--max-old-space-size=4096" +RUN pnpm --filter=app build + +# Clean up build-time-only packages from standalone output +# NOTE: @next/rspack-binding-* and @rspack/binding-* are kept — +# Next.js 16 instrumentation.js requires them at runtime. +# NOTE: @img/sharp-libvips-* is kept — sharp needs its native vips binding at runtime. +RUN cd projects/app/.next/standalone && rm -rf \ + node_modules/typescript@* + +# ========== Stage 2: Runner ========== +FROM opencloudos/opencloudos9-minimal:latest + +LABEL maintainer="OpenCloudOS Community" +LABEL org.opencontainers.image.source="https://gitee.com/OpenCloudOS/ai-agent-container" +LABEL org.opencontainers.image.description="FastGPT v4.14.9 on OpenCloudOS 9" + +# Install runtime dependencies +RUN dnf install -y \ + curl \ + ca-certificates \ + xz \ + && dnf clean all \ + && rm -rf /var/cache/yum/* \ + && update-ca-trust + +# Install Node.js 20.x LTS (runtime only) +# Use official binary tarball (NodeSource RPM repo only has 20.5.1, Next.js needs >=20.9.0) +RUN NODE_VERSION="20.20.2" \ + && ARCH=$(uname -m) \ + && case "$ARCH" in aarch64) ARCH="arm64" ;; x86_64) ARCH="x64" ;; esac \ + && curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${ARCH}.tar.xz" \ + -o /tmp/node.tar.xz \ + && tar -xJf /tmp/node.tar.xz -C /usr/local --strip-components=1 \ + && rm -f /tmp/node.tar.xz + +# Create non-root user +RUN groupadd --system --gid 1001 nodejs \ + && useradd --system --uid 1001 nextjs + +WORKDIR /app + +# Copy standalone Next.js output +COPY --from=builder --chown=nextjs:nodejs /build/projects/app/.next/standalone /app +COPY --from=builder --chown=nextjs:nodejs /build/projects/app/.next/static /app/projects/app/.next/static +COPY --from=builder --chown=nextjs:nodejs /build/projects/app/public /app/projects/app/public +COPY --from=builder --chown=root:root /build/projects/app/next.config.ts /app/projects/app/next.config.ts +COPY --from=builder --chown=nextjs:nodejs /build/projects/app/worker /app/projects/app/worker +COPY --from=builder --chown=root:root /build/projects/app/package.json /app/package.json + +# Copy data files (config.json, GeoLite2-City.mmdb, etc.) +COPY --from=builder --chown=nextjs:nodejs /build/projects/app/data /app/data + +# Copy optional runtime dependencies (dynamically imported) +COPY --from=builder --chown=root:root /build/node_modules/tiktoken /app/node_modules/tiktoken +COPY --from=builder --chown=root:root /build/node_modules/@zilliz/milvus2-sdk-node /app/node_modules/@zilliz/milvus2-sdk-node + +# Clean up tiktoken encoders (loaded on-demand, saves ~30MB) +RUN rm -rf /app/node_modules/tiktoken/encoders + +# Environment variables +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 +ENV PORT=3000 +ENV serverPath=./projects/app/server.js + +EXPOSE 3000 + +USER nextjs + +ENTRYPOINT ["sh", "-c", "node --max-old-space-size=4096 ${serverPath}"] \ No newline at end of file diff --git a/frameworks/fastgpt/4.14.9/README.md b/frameworks/fastgpt/4.14.9/README.md new file mode 100644 index 00000000..f56156ed --- /dev/null +++ b/frameworks/fastgpt/4.14.9/README.md @@ -0,0 +1,152 @@ +# FastGPT on OpenCloudOS 9 + +## 基本信息 +- **框架版本**:v4.14.9 +- **基础镜像**:opencloudos9-minimal:latest +- **Node.js 版本**:20.x +- **pnpm 版本**:9.x +- **框架类型**:大模型开发与编排平台(Next.js) +- **CUDA 版本**:N/A(CPU 框架) + +## 构建 + +```bash +docker build -t oc9-fastgpt:4.14.9 frameworks/fastgpt/4.14.9/ +``` + +> 构建需要 ≥4GB 内存(Node.js `--max-old-space-size=4096`)。 + +## 使用示例 + +FastGPT 需要配合以下外部服务一起部署: + +| 服务 | 说明 | +|------|------| +| **MongoDB** | 主数据库(≥5.0) | +| **Redis** | 缓存(≥7.0) | +| **PGVector** | 向量数据库(PostgreSQL + pgvector 扩展) | +| **MinIO** | 对象存储(S3 兼容) | + +### docker-compose 部署示例 + +```yaml +services: + fastgpt: + image: oc9-fastgpt:4.14.9 + container_name: fastgpt + restart: always + ports: + - "3000:3000" + volumes: + - ./config.json:/app/data/config.json + environment: + # 数据库 + - MONGODB_URI=mongodb://myusername:mypassword@mongo:27017/fastgpt?authSource=admin + - DB_MAX_LINK=5 + - REDIS_URL=redis://default:mypassword@redis:6379 + # 向量数据库(PGVector) + - PG_URL=postgresql://username:password@pg:5432/postgres + # 对象存储 + - STORAGE_VENDOR=minio + - STORAGE_REGION=us-east-1 + - STORAGE_ACCESS_KEY_ID=minioadmin + - STORAGE_SECRET_ACCESS_KEY=minioadmin + - STORAGE_PUBLIC_BUCKET=fastgpt-public + - STORAGE_PRIVATE_BUCKET=fastgpt-private + - STORAGE_S3_ENDPOINT=http://fastgpt-minio:9000 + - STORAGE_S3_FORCE_PATH_STYLE=true + # 应用配置 + - FE_DOMAIN=http://localhost:3000 + - ROOT_KEY=your-root-key + - TOKEN_KEY=your-token-key + - FILE_TOKEN_KEY=your-file-token-key + - AES256_SECRET_KEY=your-aes256-secret + - DEFAULT_ROOT_PSW=1234 + depends_on: + - mongo + - redis + - pg + + mongo: + image: mongo:5.0.32 + container_name: mongo + restart: always + volumes: + - ./mongo/data:/data/db + environment: + - MONGO_INITDB_ROOT_USERNAME=myusername + - MONGO_INITDB_ROOT_PASSWORD=mypassword + + redis: + image: redis:7.2-alpine + container_name: redis + restart: always + volumes: + - ./redis/data:/data + command: redis-server --requirepass mypassword --appendonly yes + + pg: + image: pgvector/pgvector:0.8.0-pg15 + container_name: pg + restart: always + volumes: + - ./pg/data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=username + - POSTGRES_PASSWORD=password + - POSTGRES_DB=postgres + + fastgpt-minio: + image: minio/minio + container_name: fastgpt-minio + restart: always + ports: + - "9000:9000" + - "9001:9001" + volumes: + - ./minio/data:/data + environment: + - MINIO_ROOT_USER=minioadmin + - MINIO_ROOT_PASSWORD=minioadmin + command: server /data --console-address ":9001" +``` + +启动后访问 `http://localhost:3000`,默认账号 `root`,默认密码 `1234`。 + +## 主要环境变量 + +| 变量 | 说明 | 默认值 | +|------|------|--------| +| `MONGODB_URI` | MongoDB 连接串 | 必填 | +| `REDIS_URL` | Redis 连接串 | 必填 | +| `PG_URL` | PostgreSQL (PGVector) 连接串 | 必填 | +| `STORAGE_VENDOR` | 存储提供商 (minio/aws-s3/cos/oss) | `minio` | +| `STORAGE_S3_ENDPOINT` | S3 兼容存储端点 | 必填 | +| `ROOT_KEY` | 最高权限密钥 | 必填 | +| `TOKEN_KEY` | Token 签名密钥 | 必填 | +| `AES256_SECRET_KEY` | AES-256 加密密钥 | 必填 | +| `FE_DOMAIN` | 前端访问地址 | `http://localhost:3000` | +| `DEFAULT_ROOT_PSW` | 默认 root 密码 | `1234` | +| `UPLOAD_FILE_MAX_SIZE` | 最大上传文件大小 (MB) | `1000` | +| `WORKFLOW_MAX_RUN_TIMES` | 最大工作流执行次数 | `1000` | + +完整环境变量列表参见官方 [`.env.template`](https://github.com/labring/FastGPT/blob/v4.14.9/projects/app/.env.template)。 + +## 测试验证 + +```bash +bash test.sh oc9-fastgpt:4.14.9 +``` + +测试脚本会验证以下内容: +- Node.js 版本 ≥ 20 +- 应用目录结构完整性 +- 关键运行时依赖(tiktoken) +- server.js 模块可解析 + +## 已知问题 + +- 构建时需要 ≥4GB 内存,内存不足会导致 Node.js OOM +- 镜像仅包含 FastGPT 应用本身,MongoDB、Redis、PGVector、MinIO 需通过 docker-compose 单独部署 +- 首次启动时需确保所有外部服务已就绪,否则应用会因数据库连接失败而退出 +- 原始 Dockerfile 使用 Alpine 基础镜像,本适配改用 OpenCloudOS 9 (RPM) 基础镜像,部分原生模块(如 `@node-rs/jieba`)可能需要额外编译 diff --git a/frameworks/fastgpt/4.14.9/build.conf b/frameworks/fastgpt/4.14.9/build.conf new file mode 100644 index 00000000..f2397f9a --- /dev/null +++ b/frameworks/fastgpt/4.14.9/build.conf @@ -0,0 +1,4 @@ +# fastgpt 4.14.9 on OpenCloudOS 9 +IMAGE_NAME=oc9-fastgpt +IMAGE_TAG=4.14.9 +GPU_TEST=false diff --git a/frameworks/fastgpt/4.14.9/test.sh b/frameworks/fastgpt/4.14.9/test.sh new file mode 100755 index 00000000..4f1319fc --- /dev/null +++ b/frameworks/fastgpt/4.14.9/test.sh @@ -0,0 +1,59 @@ +#!/bin/bash +set -e + +IMAGE="${1:?ERROR: 缺少镜像参数。用法: bash test.sh }" + +echo "=== FastGPT 4.14.9 功能测试 ===" + +# 1. 验证 Node.js 版本 >= 20 +echo -n "检查 Node.js 版本... " +docker run --rm --entrypoint node "$IMAGE" -e " +const v = process.versions.node.split('.').map(Number); +if (v[0] < 20) { console.error('Node.js >= 20 required, got ' + process.versions.node); process.exit(1); } +console.log('Node.js ' + process.versions.node); +" && echo "✓ 通过" || { echo "✗ 失败"; exit 1; } + +# 2. 验证应用目录结构 +echo -n "检查应用目录结构... " +docker run --rm --entrypoint node "$IMAGE" -e " +const fs = require('fs'); +const checks = [ + './projects/app/server.js', + './projects/app/public', + './projects/app/.next/static', + './projects/app/worker', + './data/config.json' +]; +checks.forEach(p => { + if (!fs.existsSync(p)) { console.error('Missing: ' + p); process.exit(1); } +}); +console.log('目录结构完整'); +" && echo "✓ 通过" || { echo "✗ 失败"; exit 1; } + +# 3. 验证关键 node_modules 存在 +echo -n "检查关键依赖... " +docker run --rm --entrypoint node "$IMAGE" -e " +const fs = require('fs'); +const mods = ['tiktoken']; +mods.forEach(m => { + if (!fs.existsSync('./node_modules/' + m)) { console.error('Missing module: ' + m); process.exit(1); } +}); +console.log('关键依赖完整'); +" && echo "✓ 通过" || { echo "✗ 失败"; exit 1; } + +# 4. 验证 server.js 存在且为有效 JS(不启动服务器,避免触发 instrumentation 原生绑定加载) +echo -n "检查 server.js 有效性... " +docker run --rm --entrypoint node "$IMAGE" -e " +const fs = require('fs'); +const path = './projects/app/server.js'; +if (!fs.existsSync(path)) { console.error('Missing: ' + path); process.exit(1); } +const src = fs.readFileSync(path, 'utf8'); +// Verify it looks like a valid Node.js entry (contains expected keywords) +const keywords = ['require', 'next']; +keywords.forEach(kw => { + if (!src.includes(kw)) { console.error('server.js missing expected keyword: ' + kw); process.exit(1); } +}); +console.log('server.js 结构正常'); +" && echo "✓ 通过" || { echo "✗ 失败"; exit 1; } + +echo "=== 所有测试通过 ===" \ No newline at end of file -- Gitee