一、项目介绍
WeKnora(维娜拉) 是一款开源的、基于大语言模型(LLM)的知识管理框架,专为企业级文档理解、语义检索与智能推理场景打造。
框架围绕三大核心能力构建:RAG 快速问答适合日常知识查询,ReAct Agent 智能推理自主编排知识检索、MCP 工具与网络搜索完成复杂多步任务,全新的 Wiki 模式则让 Agent 从原始文档中自治生成相互链接的 Markdown 知识库与可视化知识图谱。结合多源数据接入(飞书 / Notion / 语雀 / RSS,更多持续接入中)、网站嵌入 Widget 将智能体发布到外部站点、权限范围 API Key 与 Principal 模型面向程序化集成、每空间多实例存储后端灵活编排数据落地、二十余家主流模型厂商集成、Langfuse 全链路可观测性与运行时任务队列面板 + Worker 池治理、企业级多空间 RBAC(四级角色矩阵 + 资源归属 + 空间审计日志),以及完全可私有化部署的模块化架构,WeKnora 帮助团队把分散文档沉淀为可查询、可推理、可持续演进的专属知识资产。
框架支持从飞书、Notion 及语雀等外部平台自动同步知识(更多数据源持续接入中),覆盖 PDF、Word、图片、Excel 等十余种文档格式,并可通过企业微信、飞书、Slack、Telegram 等 IM 频道直接提供问答服务。模型层面兼容 OpenAI、DeepSeek、Qwen(阿里云)、智谱、混元、Gemini、MiniMax、NVIDIA、Ollama 等主流厂商。全流程模块化设计,大模型、向量数据库、存储等组件均可灵活替换,支持本地与私有云部署,数据完全自主可控。WeKnora 还无缝集成了 Langfuse,为 Agent 运行、Token 使用及任务流水线提供了全面的可观测性追踪。
二、搭建教程(型号DH4300PLUS,同样适用X86机型)
1、打开文件管理器-找到docker共享文件夹-创建一个文件夹weknora;
2、下载项目到电脑文件夹-解压-编辑.env.example文件-全选内容复制粘贴一下内容;
# =================================================================
# WeKnora 环境变量配置(绿联云 UGOS Pro 专用)
# 生成日期:2026-07-17
# 说明:
# 1. 端口已调至 20000+ 避免与 NAS 系统服务冲突
# 2. 所有密码/密钥均为强随机值,请妥善保管
# 3. AES 密钥为 64 位十六进制(即 32 字节),符合 AES-256 要求
# 4. 若无需 Langfuse 可观测性,请注释掉 LANGFUSE_PUBLIC_KEY 和 SECRET_KEY
# =================================================================
# ---------- 基础设置 ----------
# 镜像版本:latest(稳定版)或 main(最新开发版)
WEKNORA_VERSION=latest
# Gin 运行模式:release(生产)或 debug(开发)
GIN_MODE=release
# 日志级别:debug / info / warn / error / fatal
LOG_LEVEL=debug
# 时区(影响日志时间戳和任务调度)
TZ=Asia/Shanghai
# 系统默认语言(BCP-47 格式)
WEKNORA_LANGUAGE=zh-CN
# ---------- 端口映射(宿主机端口,可安全修改) ----------
# 前端 Web 端口(原 80 -> 28080,避免与 NAS 管理界面冲突)
FRONTEND_PORT=28080
# 后端 API 服务端口(原 8080 -> 28081)
APP_PORT=28081
# 说明:以下内部端口无需修改,保持默认即可
# APP_BACKEND_PORT=8080 # 容器内后端监听端口(不要改)
# DB_PORT=5432 # PostgreSQL 容器内端口(不要改)
# REDIS_ADDR=redis:6379 # Redis 内部地址(不要改)
# ---------- 数据库配置(PostgreSQL/ParadeDB) ----------
# 数据库驱动(仅支持 postgres)
DB_DRIVER=postgres
# 数据库主机(内部服务名,不要改)
DB_HOST=postgres
# 数据库内部端口(容器内监听 5432,不要改)
DB_PORT=5432
# 数据库用户名
DB_USER=postgres
# 【必须修改】数据库密码(强随机,含特殊字符,已在 compose 中正确处理)
DB_PASSWORD=Ug9#kL2$mNpQ5&xZvR7wY3@
# 数据库名称
DB_NAME=WeKnora
# ---------- Redis 配置 ----------
# Redis 主机地址(内部服务名)
REDIS_ADDR=redis:6379
# 【必须修改】Redis 密码(强随机)
REDIS_PASSWORD=Fa8#sD4&hJkL9*PqW2@
# Redis 数据库索引(0-15,WeKnora 使用 0)
REDIS_DB=0
# Redis key 前缀(用于命名空间隔离)
REDIS_PREFIX=stream:
# 流处理器类型(redis 或 memory)
STREAM_MANAGER_TYPE=redis
# ---------- 存储配置 ----------
# 向量检索驱动(postgres / qdrant / milvus / weaviate / elasticsearch 等)
RETRIEVE_DRIVER=postgres
# 文件存储类型(local / minio / cos / tos / s3 / obs)
STORAGE_TYPE=local
# 本地存储基础目录(容器内路径,由卷持久化)
LOCAL_STORAGE_BASE_DIR=/data/files
# 是否自动恢复脏数据
AUTO_RECOVER_DIRTY=true
# ---------- AES 加密密钥(必须 32 字节) ----------
# 说明:此处使用 64 位十六进制表示(每个字符 4 位,共 64 字符 = 32 字节)
# 若需重新生成,可执行:openssl rand -hex 32
# 租户 AES 密钥
TENANT_AES_KEY=8f7e2d1a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e
# 系统 AES 密钥
SYSTEM_AES_KEY=1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2
# ---------- 安全与认证 ----------
# JWT 签名密钥(64 位十六进制,安全强度高)
JWT_SECRET=4f8e2d1a7b3c9e5f0d6a8b4c2e7f1a3d5b8c0e2f4a6d8b1c3e5f7a9c0d2e4f6
# 是否禁止新用户公开注册(生产环境建议 true)
DISABLE_REGISTRATION=false
# 注册后默认空间策略(create_personal / tenantless)
# WEKNORA_AUTH_DEFAULT_TENANT_MODE=create_personal
# 是否允许普通用户主动创建空间(默认 true)
# WEKNORA_TENANT_SELF_SERVICE_CREATION_ENABLED=true
# ---------- 外部服务地址 ----------
# Ollama 服务地址(若在宿主机运行,保持 host.docker.internal)
OLLAMA_BASE_URL=http://host.docker.internal:11434
# Docreader 服务地址(内部服务名)
DOCREADER_ADDR=docreader:50051
DOCREADER_TRANSPORT=grpc
# ---------- 并发与性能 ----------
# 嵌入/模型并发数(遇 429 可调小)
CONCURRENCY_POOL_SIZE=5
# 异步任务并发(可根据机器性能调整)
# WEKNORA_ASYNQ_CORE_CONCURRENCY=8
# WEKNORA_ASYNQ_POSTPROCESS_CONCURRENCY=2
# WEKNORA_ASYNQ_ENRICHMENT_CONCURRENCY=12
# WEKNORA_ASYNQ_MAINTENANCE_CONCURRENCY=4
# WEKNORA_ASYNQ_SHARED_CONCURRENCY=6
# WEKNORA_WIKI_ASYNQ_CONCURRENCY=8
# WEKNORA_MODEL_MAX_CONCURRENCY=32
# ---------- 知识图谱(Neo4j) ----------
# 是否启用图 RAG(需额外资源,默认关闭)
ENABLE_GRAPH_RAG=false
# Neo4j 连接参数(若启用请取消注释并配置)
# NEO4J_ENABLE=false
# NEO4J_URI=bolt://neo4j:7687
# NEO4J_USERNAME=neo4j
# NEO4J_PASSWORD=password
# ---------- Agent 沙箱 ----------
# 沙箱模式:docker / local / disabled
WEKNORA_SANDBOX_MODE=docker
# 脚本执行超时(秒)
WEKNORA_SANDBOX_TIMEOUT=60
# Agent LLM 调用超时(秒),复杂任务可调大
# WEKNORA_AGENT_LLM_TIMEOUT=300
# MCP 工具人工审核等待超时(秒)
# WEKNORA_AGENT_TOOL_APPROVAL_TIMEOUT=600
# ---------- 租户与 RBAC ----------
# 启用空间级 RBAC(默认 true)
# WEKNORA_TENANT_ENABLE_RBAC=true
# 单个用户最大可创建空间数(0 使用默认,-1 关闭限制)
# WEKNORA_TENANT_MAX_OWNED_PER_USER=
# 创建空间时是否自动生成全量 API Key(默认 false)
# WEKNORA_TENANT_AUTO_CREATE_API_KEY=false
# 系统管理员引导邮箱(首次启动自动提权)
# WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL=
# ---------- 聊天附件与 OCR ----------
# 附件保留时间(小时)
# WEKNORA_CHAT_ATTACHMENT_TTL_HOURS=24
# 附件解析等待超时(秒)
# WEKNORA_CHAT_ATTACHMENT_WAIT_TIMEOUT_SEC=60
# OCR 并发数
# WEKNORA_CHAT_ATTACHMENT_OCR_CONCURRENCY=8
# OCR 最大页数
# WEKNORA_CHAT_ATTACHMENT_OCR_MAX_PAGES=8
# ---------- SSRF 白名单 ----------
# 默认已包含内置服务(searxng, qdrant, milvus, weaviate, doris-fe)
# 若需添加自定义地址,请追加到 SSRF_WHITELIST_EXTRA
SSRF_WHITELIST_EXTRA=searxng,qdrant,milvus,weaviate,doris-fe
# ---------- Langfuse 可观测性(可选) ----------
# 注意:若不使用,请将下面两行注释掉,否则应用启动会尝试连接 Langfuse
# LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxx
# LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxx
# 若自建 Langfuse,取消注释并设置 HOST
# LANGFUSE_HOST=http://langfuse-web:3000
# 其他 Langfuse 参数(可选)
# LANGFUSE_RELEASE=v0.4.2
# LANGFUSE_ENVIRONMENT=production
# LANGFUSE_FLUSH_AT=15
# LANGFUSE_SAMPLE_RATE=1.0
# ---------- APK 镜像源(加速 Alpine 构建) ----------
APK_MIRROR_ARG=mirrors.tencent.com
# ---------- 以下为高级存储配置(按需启用) ----------
# 若需使用 MinIO,取消注释并配置,同时启用 profile minio
# MINIO_ENDPOINT=minio:9000
# MINIO_ACCESS_KEY_ID=minioadmin
# MINIO_SECRET_ACCESS_KEY=minioadmin
# MINIO_BUCKET_NAME=weknora
# 腾讯云 COS
# COS_SECRET_ID=xxx
# COS_SECRET_KEY=xxx
# COS_REGION=ap-guangzhou
# COS_BUCKET_NAME=xxx
# COS_APP_ID=xxx
# COS_PATH_PREFIX=weknora/
# COS_ENABLE_OLD_DOMAIN=true
# 华为 OBS
# OBS_ENDPOINT=obs.cn-north-4.myhuaweicloud.com
# OBS_REGION=cn-north-4
# OBS_ACCESS_KEY=xxx
# OBS_SECRET_KEY=xxx
# OBS_BUCKET_NAME=xxx
# OBS_PATH_PREFIX=weknora/
# AWS S3
# S3_ENDPOINT=https://s3.amazonaws.com
# S3_REGION=us-east-1
# S3_ACCESS_KEY=xxx
# S3_SECRET_KEY=xxx
# S3_BUCKET_NAME=xxx
# S3_PATH_PREFIX=weknora/
# ---------- 其他向量数据库(按需启用) ----------
# Qdrant
# QDRANT_HOST=qdrant
# QDRANT_PORT=6334
# QDRANT_COLLECTION=weknora_embeddings
# Milvus
# MILVUS_ADDRESS=milvus:19530
# MILVUS_COLLECTION=weknora_embeddings
# MILVUS_METRIC_TYPE=IP
# Weaviate
# WEAVIATE_HOST=weaviate:8080
# WEAVIATE_GRPC_ADDRESS=weaviate:50051
# WEAVIATE_SCHEME=http
# WEAVIATE_AUTH_ENABLED=false
# Doris
# DORIS_ADDR=doris-fe:9030
# DORIS_HTTP_PORT=8030
# DORIS_DATABASE=weknora
# DORIS_USERNAME=root
# DORIS_PASSWORD=
# DORIS_TABLE_PREFIX=weknora_embeddings
# ---------- 文件上传大小限制 ----------
# MAX_FILE_SIZE_MB=50
# ---------- 外部访问 URL(用于 IM 渠道) ----------
# APP_EXTERNAL_URL=http://你的公网IP:28080
3、保存后把文件名修改为.env,然后打开文件管理器,找到左小角设置-隐藏指定文件-取消以点开头-保存;


4、把解压的所有文件传到weknora文件夹,文件较多一定要等待所有文件传输完成;

5、打开docker-选择项目-创建-输入项目名weknora-自动带出存放路径;

6、把下方docker compose粘贴进去;
# =============================================================================
# WeKnora Docker Compose 配置(绿联云 UGOS Pro 专用)
# 版本:最新稳定版
# 说明:所有可变值均通过 .env 文件注入,请勿硬编码敏感信息
# 使用前请确保 ./config/config.yaml 存在,且 Redis 密码不含易被 shell 截断的字符
# =============================================================================
# ---------- 网络定义 ----------
# 所有服务共享此内部网络,通过服务名(如 app、postgres)互相访问
networks:
WeKnora-network:
driver: bridge
# ---------- 卷定义 ----------
# 命名卷由 Docker 管理,数据保存在 Docker 数据目录(如 /var/lib/docker/volumes/)
# 建议定期备份 postgres-data 和 data-files(核心业务数据)
volumes:
postgres-data: # PostgreSQL 数据库文件(最重要!)
data-files: # 用户上传的文档、图片等(核心数据)
docreader-tmp: # 文档解析临时文件(可随时清理)
minio_data: # MinIO 对象存储数据(若启用 minio profile)
neo4j-data: # Neo4j 图数据库数据(若启用 neo4j profile)
qdrant_data: # Qdrant 向量库数据(若启用 qdrant profile)
milvus_data: # Milvus 向量库数据(若启用 milvus profile)
weaviate_data: # Weaviate 向量库数据(若启用 weaviate profile)
doris_fe_meta: # Doris FE 元数据(若启用 doris profile)
doris_fe_log: # Doris FE 日志
doris_be_storage: # Doris BE 存储
doris_be_log: # Doris BE 日志
langfuse_clickhouse_data: # Langfuse ClickHouse 数据(若启用 langfuse profile)
langfuse_clickhouse_logs: # Langfuse ClickHouse 日志
langfuse_minio_data: # Langfuse 专用 MinIO 数据
searxng_config: # SearXNG 配置文件卷(若启用 searxng profile)
# ---------- 服务定义 ----------
services:
# ============================================================
# 1. 前端服务 (frontend)
# 基于 Nginx 提供 Web 界面,并反向代理 API 请求到后端
# ============================================================
frontend:
image: wechatopenai/weknora-ui:${WEKNORA_VERSION:-latest}
# 若需本地构建,需先执行 ./scripts/build_frontend_dist.sh
build:
context: ./frontend
container_name: WeKnora-frontend
# 宿主机端口由 FRONTEND_PORT 控制(默认 80,现已改为 28080)
ports:
- "${FRONTEND_PORT:-80}:80"
environment:
- MAX_FILE_SIZE_MB=${MAX_FILE_SIZE_MB:-50}
- APP_HOST=${APP_HOST:-app} # 后端服务名(容器内 DNS)
- APP_PORT=${APP_BACKEND_PORT:-8080} # 后端容器监听端口
- APP_SCHEME=${APP_SCHEME:-http} # 协议(http/https)
depends_on:
app:
condition: service_healthy # 等待 app 健康后再启动
networks:
- WeKnora-network
restart: unless-stopped
# ============================================================
# 2. 后端应用服务 (app)
# 核心业务:知识库管理、对话、检索、Agent、文件处理等
# ============================================================
app:
image: wechatopenai/weknora-app:${WEKNORA_VERSION:-latest}
build:
context: .
dockerfile: docker/Dockerfile.app
args:
- APK_MIRROR_ARG=${APK_MIRROR_ARG:-} # Alpine 镜像源加速(如 mirrors.tencent.com)
container_name: WeKnora-app
# 宿主机端口由 APP_PORT 控制(默认 8080,现已改为 28081)
ports:
- "${APP_PORT:-8080}:8080"
volumes:
# --- 命名卷(Docker 管理,推荐用于有状态数据) ---
- data-files:/data/files # 上传文件持久化(务必定期备份)
- docreader-tmp:/tmp/docreader:ro # 只读挂载 docreader 临时目录
# --- 绑定挂载(相对路径,便于直接编辑) ---
- ./config/config.yaml:/app/config/config.yaml # 主配置文件(必须存在!)
- ./skills/preloaded:/app/skills/preloaded # 自定义技能目录(可选)
# 若需内置模型声明,可复制 config/builtin_models.yaml.example 并取消注释下行
# - ./config/builtin_models.yaml:/app/config/builtin_models.yaml:ro
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# 从 .env 加载全部环境变量,供配置文件(如 builtin_models.yaml)使用 ${VAR} 引用
env_file:
- .env
environment:
# 以下所有变量均从 .env 读取,若未设置则使用默认值
- LOG_LEVEL=${LOG_LEVEL:-}
# --- 对象存储(腾讯云 COS) ---
- COS_SECRET_ID=${COS_SECRET_ID:-}
- COS_SECRET_KEY=${COS_SECRET_KEY:-}
- COS_REGION=${COS_REGION:-}
- COS_BUCKET_NAME=${COS_BUCKET_NAME:-}
- COS_APP_ID=${COS_APP_ID:-}
- COS_PATH_PREFIX=${COS_PATH_PREFIX:-}
- COS_ENABLE_OLD_DOMAIN=${COS_ENABLE_OLD_DOMAIN:-}
# --- 运行模式与安全 ---
- GIN_MODE=${GIN_MODE:-release}
- DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false}
- WEKNORA_AUTH_DEFAULT_TENANT_MODE=${WEKNORA_AUTH_DEFAULT_TENANT_MODE:-}
- WEKNORA_TENANT_SELF_SERVICE_CREATION_ENABLED=${WEKNORA_TENANT_SELF_SERVICE_CREATION_ENABLED:-}
# --- 数据库(PostgreSQL) ---
- DB_DRIVER=${DB_DRIVER:-postgres}
- DB_HOST=${DB_HOST:-postgres} # 内部服务名,不要改
- DB_PORT=${DB_PORT:-5432} # 容器内部端口,不要改!
- DB_USER=${DB_USER:-}
- DB_PASSWORD=${DB_PASSWORD:-}
- DB_NAME=${DB_NAME:-}
- TZ=${TZ:-Asia/Shanghai}
- WEKNORA_LANGUAGE=${WEKNORA_LANGUAGE:-zh-CN}
# --- Langfuse 可观测性(可选) ---
# 同时设置 PUBLIC_KEY 和 SECRET_KEY 即自动启用
- LANGFUSE_ENABLED=${LANGFUSE_ENABLED:-}
- LANGFUSE_HOST=${LANGFUSE_HOST:-https://cloud.langfuse.com}
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY:-}
- LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY:-}
- LANGFUSE_RELEASE=${LANGFUSE_RELEASE:-}
- LANGFUSE_ENVIRONMENT=${LANGFUSE_ENVIRONMENT:-}
- LANGFUSE_FLUSH_AT=${LANGFUSE_FLUSH_AT:-}
- LANGFUSE_FLUSH_INTERVAL=${LANGFUSE_FLUSH_INTERVAL:-}
- LANGFUSE_QUEUE_SIZE=${LANGFUSE_QUEUE_SIZE:-}
- LANGFUSE_REQUEST_TIMEOUT=${LANGFUSE_REQUEST_TIMEOUT:-}
- LANGFUSE_SAMPLE_RATE=${LANGFUSE_SAMPLE_RATE:-}
- LANGFUSE_DEBUG=${LANGFUSE_DEBUG:-}
# --- 向量检索驱动 ---
- RETRIEVE_DRIVER=${RETRIEVE_DRIVER:-}
# Elasticsearch
- ELASTICSEARCH_ADDR=${ELASTICSEARCH_ADDR:-}
- ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME:-}
- ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD:-}
- ELASTICSEARCH_INDEX=${ELASTICSEARCH_INDEX:-}
# Qdrant
- QDRANT_HOST=${QDRANT_HOST:-qdrant}
- QDRANT_PORT=${QDRANT_PORT:-6334}
- QDRANT_COLLECTION=${QDRANT_COLLECTION:-weknora_embeddings}
- QDRANT_API_KEY=${QDRANT_API_KEY:-}
- QDRANT_USE_TLS=${QDRANT_USE_TLS:-false}
# Milvus
- MILVUS_ADDRESS=${MILVUS_ADDRESS:-milvus:19530}
- MILVUS_COLLECTION=${MILVUS_COLLECTION:-weknora_embeddings}
- MILVUS_METRIC_TYPE=${MILVUS_METRIC_TYPE:-IP}
# --- 文档解析服务 ---
- DOCREADER_ADDR=${DOCREADER_ADDR:-docreader:50051}
- DOCREADER_TRANSPORT=${DOCREADER_TRANSPORT:-grpc}
- GRPC_TLS_ENABLED=${GRPC_TLS_ENABLED:-false}
- GRPC_TLS_CERT=${GRPC_TLS_CERT:-}
- GRPC_TLS_KEY=${GRPC_TLS_KEY:-}
- GRPC_TLS_CA=${GRPC_TLS_CA:-}
- GRPC_TLS_SERVER_NAME=${GRPC_TLS_SERVER_NAME:-}
- GRPC_AUTH_TOKEN=${GRPC_AUTH_TOKEN:-}
# Weaviate
- WEAVIATE_HOST=${WEAVIATE_HOST:-weaviate:8080}
- WEAVIATE_GRPC_ADDRESS=${WEAVIATE_GRPC_ADDRESS:-weaviate:50051}
- WEAVIATE_SCHEME=${WEAVIATE_SCHEME:-http}
- WEAVIATE_AUTH_ENABLED=${WEAVIATE_AUTH_ENABLED:-false}
- WEAVIATE_API_KEY=${WEAVIATE_API_KEY:-}
# Apache Doris
- DORIS_ADDR=${DORIS_ADDR:-doris-fe:9030}
- DORIS_HTTP_PORT=${DORIS_HTTP_PORT:-8030}
- DORIS_DATABASE=${DORIS_DATABASE:-weknora}
- DORIS_USERNAME=${DORIS_USERNAME:-root}
- DORIS_PASSWORD=${DORIS_PASSWORD:-}
- DORIS_TABLE_PREFIX=${DORIS_TABLE_PREFIX:-weknora_embeddings}
- DORIS_COMPAT_MODE=${DORIS_COMPAT_MODE:-auto}
# --- 文件存储 ---
- STORAGE_TYPE=${STORAGE_TYPE:-}
- LOCAL_STORAGE_BASE_DIR=${LOCAL_STORAGE_BASE_DIR:-}
- AUTO_RECOVER_DIRTY=${AUTO_RECOVER_DIRTY:-true}
# MinIO
- MINIO_ENDPOINT=${MINIO_ENDPOINT:-minio:9000}
- MINIO_ACCESS_KEY_ID=${MINIO_ACCESS_KEY_ID:-minioadmin}
- MINIO_SECRET_ACCESS_KEY=${MINIO_SECRET_ACCESS_KEY:-minioadmin}
- MINIO_BUCKET_NAME=${MINIO_BUCKET_NAME:-}
# 华为 OBS
- OBS_ENDPOINT=${OBS_ENDPOINT:-}
- OBS_REGION=${OBS_REGION:-}
- OBS_ACCESS_KEY=${OBS_ACCESS_KEY:-}
- OBS_SECRET_KEY=${OBS_SECRET_KEY:-}
- OBS_BUCKET_NAME=${OBS_BUCKET_NAME:-}
- OBS_PATH_PREFIX=${OBS_PATH_PREFIX:-}
- OBS_PROXY_DOMAIN=${OBS_PROXY_DOMAIN:-}
# --- Ollama ---
- OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
# --- 流管理 ---
- STREAM_MANAGER_TYPE=${STREAM_MANAGER_TYPE:-}
# --- Redis ---
- REDIS_ADDR=${REDIS_ADDR:-redis:6379}
- REDIS_USERNAME=${REDIS_USERNAME:-}
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
- REDIS_DB=${REDIS_DB:-}
- REDIS_PREFIX=${REDIS_PREFIX:-}
# --- 图 RAG(Neo4j) ---
- ENABLE_GRAPH_RAG=${ENABLE_GRAPH_RAG:-}
- NEO4J_ENABLE=${NEO4J_ENABLE:-}
- NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687}
- NEO4J_USERNAME=${NEO4J_USERNAME:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD:-password}
# --- 加密密钥 ---
- TENANT_AES_KEY=${TENANT_AES_KEY:-}
- SYSTEM_AES_KEY=${SYSTEM_AES_KEY:-}
# --- SSRF 白名单 ---
- SSRF_WHITELIST=${SSRF_WHITELIST:-}
- IMAGE_HOST_KEEP_URL=${IMAGE_HOST_KEEP_URL:-}
- SSRF_WHITELIST_EXTRA=${SSRF_WHITELIST_EXTRA:-searxng,qdrant,milvus,weaviate,doris-fe}
# --- 并发与性能 ---
- CONCURRENCY_POOL_SIZE=${CONCURRENCY_POOL_SIZE:-5}
- JWT_SECRET=${JWT_SECRET:-}
- CRYPTO_MASTER_KEY=${CRYPTO_MASTER_KEY:-}
- CRYPTO_SALT=${CRYPTO_SALT:-}
- MAX_FILE_SIZE_MB=${MAX_FILE_SIZE_MB:-50}
# --- 聊天附件 ---
- WEKNORA_CHAT_ATTACHMENT_TTL_HOURS=${WEKNORA_CHAT_ATTACHMENT_TTL_HOURS:-24}
- WEKNORA_CHAT_ATTACHMENT_WAIT_TIMEOUT_SEC=${WEKNORA_CHAT_ATTACHMENT_WAIT_TIMEOUT_SEC:-60}
- WEKNORA_CHAT_ATTACHMENT_OCR_CONCURRENCY=${WEKNORA_CHAT_ATTACHMENT_OCR_CONCURRENCY:-8}
- WEKNORA_CHAT_ATTACHMENT_OCR_MAX_PAGES=${WEKNORA_CHAT_ATTACHMENT_OCR_MAX_PAGES:-8}
# --- Agent 沙箱 ---
- WEKNORA_SANDBOX_MODE=${WEKNORA_SANDBOX_MODE:-docker}
- WEKNORA_SANDBOX_TIMEOUT=${WEKNORA_SANDBOX_TIMEOUT:-60}
- WEKNORA_SANDBOX_DOCKER_IMAGE=${WEKNORA_SANDBOX_DOCKER_IMAGE:-wechatopenai/weknora-sandbox:${WEKNORA_VERSION:-latest}}
- WEKNORA_AGENT_LLM_TIMEOUT=${WEKNORA_AGENT_LLM_TIMEOUT:-}
- WEKNORA_AGENT_TOOL_APPROVAL_TIMEOUT=${WEKNORA_AGENT_TOOL_APPROVAL_TIMEOUT:-}
# --- 租户 RBAC ---
- WEKNORA_TENANT_ENABLE_RBAC=${WEKNORA_TENANT_ENABLE_RBAC:-}
- WEKNORA_TENANT_MAX_OWNED_PER_USER=${WEKNORA_TENANT_MAX_OWNED_PER_USER:-}
- WEKNORA_TENANT_AUTO_CREATE_API_KEY=${WEKNORA_TENANT_AUTO_CREATE_API_KEY:-}
# --- 异步任务并发控制 ---
- WEKNORA_ASYNQ_CORE_CONCURRENCY=${WEKNORA_ASYNQ_CORE_CONCURRENCY:-8}
- WEKNORA_ASYNQ_POSTPROCESS_CONCURRENCY=${WEKNORA_ASYNQ_POSTPROCESS_CONCURRENCY:-2}
- WEKNORA_ASYNQ_ENRICHMENT_CONCURRENCY=${WEKNORA_ASYNQ_ENRICHMENT_CONCURRENCY:-12}
- WEKNORA_ASYNQ_MAINTENANCE_CONCURRENCY=${WEKNORA_ASYNQ_MAINTENANCE_CONCURRENCY:-4}
- WEKNORA_ASYNQ_SHARED_CONCURRENCY=${WEKNORA_ASYNQ_SHARED_CONCURRENCY:-6}
- WEKNORA_WIKI_ASYNQ_CONCURRENCY=${WEKNORA_WIKI_ASYNQ_CONCURRENCY:-8}
- WEKNORA_MODEL_MAX_CONCURRENCY=${WEKNORA_MODEL_MAX_CONCURRENCY:-32}
- APK_MIRROR_ARG=${APK_MIRROR_ARG:-}
- WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL=${WEKNORA_BOOTSTRAP_SYSTEM_ADMIN_EMAIL:-}
depends_on:
redis:
condition: service_started
postgres:
condition: service_healthy
docreader:
condition: service_healthy
networks:
- WeKnora-network
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway" # 使容器能访问宿主机的 Ollama 等服务
# ============================================================
# 3. 沙箱服务 (sandbox)
# 仅用于构建/拉取沙箱镜像,实际 Skills 执行由 app 通过 Docker API 按需启动
# ============================================================
sandbox:
image: wechatopenai/weknora-sandbox:${WEKNORA_VERSION:-latest}
container_name: WeKnora-sandbox
build:
context: .
dockerfile: docker/Dockerfile.sandbox
profiles:
- full
command: ["true"]
restart: "no"
# ============================================================
# 4. 文档解析服务 (docreader)
# 提供 gRPC 接口,用于 PDF、Office、图片的解析、OCR 和版式识别
# ============================================================
docreader:
image: wechatopenai/weknora-docreader:${WEKNORA_VERSION:-latest}
build:
context: .
dockerfile: docker/Dockerfile.docreader
args:
- APT_MIRROR=${APT_MIRROR:-}
container_name: WeKnora-docreader
expose:
- "50051" # 仅内部网络可访问,不映射到宿主机
volumes:
- docreader-tmp:/tmp/docreader
environment:
- TZ=${TZ:-Asia/Shanghai}
- DOCREADER_IMAGE_OUTPUT_DIR=/tmp/docreader
- DOCREADER_PDF_FORCE_SCANNED=${DOCREADER_PDF_FORCE_SCANNED:-false}
- MAX_FILE_SIZE_MB=${MAX_FILE_SIZE_MB:-}
- DOCREADER_ODL_MAX_WORKERS=${DOCREADER_ODL_MAX_WORKERS:-1}
- DOCREADER_ODL_HYBRID=${DOCREADER_ODL_HYBRID:-off}
- DOCREADER_ODL_HYBRID_URL=${DOCREADER_ODL_HYBRID_URL:-http://odl-hybrid:5002}
- DOCREADER_ODL_HYBRID_MODE=${DOCREADER_ODL_HYBRID_MODE:-auto}
- DOCREADER_ODL_HYBRID_FALLBACK=${DOCREADER_ODL_HYBRID_FALLBACK:-false}
- DOCREADER_ODL_MARKDOWN_WITH_HTML=${DOCREADER_ODL_MARKDOWN_WITH_HTML:-false}
- DOCREADER_MARKITDOWN_MAX_WORKERS=${DOCREADER_MARKITDOWN_MAX_WORKERS:-1}
- DOCREADER_PDF_RENDER_MAX_WORKERS=${DOCREADER_PDF_RENDER_MAX_WORKERS:-1}
- DOCREADER_PDF_RENDER_DPI=${DOCREADER_PDF_RENDER_DPI:-200}
- DOCREADER_PDF_JPEG_QUALITY=${DOCREADER_PDF_JPEG_QUALITY:-90}
- GRPC_TLS_ENABLED=${GRPC_TLS_ENABLED:-false}
- GRPC_TLS_CERT=${GRPC_TLS_CERT:-}
- GRPC_TLS_KEY=${GRPC_TLS_KEY:-}
- GRPC_TLS_CA=${GRPC_TLS_CA:-}
- GRPC_AUTH_TOKEN=${GRPC_AUTH_TOKEN:-}
healthcheck:
test: ["CMD", "grpc_health_probe", "-addr=localhost:50051"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
networks:
- WeKnora-network
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
# ============================================================
# 5. OpenDataLoader Hybrid(可选增强解析器)
# 启用 profile odl-hybrid 并本地构建(镜像 tag: local)
# ============================================================
odl-hybrid:
build:
context: .
dockerfile: docker/Dockerfile.odl-hybrid
image: weknora-odl-hybrid:local
container_name: WeKnora-odl-hybrid
profiles:
- odl-hybrid
expose:
- "5002"
environment:
- ODL_HYBRID_EXTRA_ARGS=${ODL_HYBRID_EXTRA_ARGS:---no-ocr}
networks:
- WeKnora-network
restart: unless-stopped
# ============================================================
# 6. PostgreSQL + ParadeDB(主数据库)
# 存储业务数据、向量嵌入、全文检索
# ============================================================
postgres:
image: paradedb/paradedb:v0.22.2-pg17
container_name: WeKnora-postgres
environment:
- POSTGRES_USER=${DB_USER}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- POSTGRES_DB=${DB_NAME}
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- WeKnora-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 10s
timeout: 10s
retries: 3
start_period: 30s
restart: unless-stopped
stop_grace_period: 1m
# 若需从宿主机外部连接数据库(如 pgAdmin),可取消注释下行
# ports:
# - "25432:5432"
# ============================================================
# 7. Redis(缓存 / 消息队列)
# 注意:command 使用数组格式,避免密码中的特殊字符被 shell 截断
# ============================================================
redis:
image: redis:7.0-alpine
container_name: WeKnora-redis
command:
- redis-server
- --appendonly
- yes
- --requirepass
- ${REDIS_PASSWORD}
restart: always
networks:
- WeKnora-network
# ============================================================
# 8. SearXNG 初始化器(一次性)
# 将模板 settings.yml 复制到配置卷
# ============================================================
searxng-init:
image: busybox:1.36
container_name: WeKnora-searxng-init
command: ["sh", "-c", "cp /template/settings.yml /etc/searxng/settings.yml && chmod 0644 /etc/searxng/settings.yml"]
volumes:
- ./docker/searxng/settings.yml:/template/settings.yml:ro
- searxng_config:/etc/searxng
restart: "no"
networks:
- WeKnora-network
profiles:
- searxng
- full
# ============================================================
# 9. SearXNG 搜索引擎(可选)
# 提供元搜索能力,默认仅绑定 127.0.0.1 确保安全
# ============================================================
searxng:
image: searxng/searxng:latest
container_name: WeKnora-searxng
ports:
- "${SEARXNG_BIND:-127.0.0.1}:${SEARXNG_PORT:-8888}:8080"
volumes:
- searxng_config:/etc/searxng
environment:
- SEARXNG_BASE_URL=http://localhost:${SEARXNG_PORT:-8888}/
- INSTANCE_NAME=weknora-searxng
- SEARXNG_SECRET=${SEARXNG_SECRET:-weknora-default-searxng-secret-rotate-before-exposing-publicly}
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
restart: unless-stopped
depends_on:
searxng-init:
condition: service_completed_successfully
networks:
- WeKnora-network
profiles:
- searxng
- full
# ============================================================
# 10. MinIO(可选对象存储)
# 启用 profile minio 后使用,替代 local 存储
# ============================================================
minio:
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
container_name: WeKnora-minio
ports:
- "${MINIO_PORT:-9000}:9000"
- "${MINIO_CONSOLE_PORT:-9001}:9001"
environment:
- MINIO_ROOT_USER=${MINIO_ACCESS_KEY_ID:-minioadmin}
- MINIO_ROOT_PASSWORD=${MINIO_SECRET_ACCESS_KEY:-minioadmin}
command: server --console-address ":9001" /data
volumes:
- minio_data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
networks:
- WeKnora-network
profiles:
- minio
- full
# ============================================================
# 11. Neo4j(可选图数据库)
# 用于知识图谱构建,启用 profile neo4j
# ============================================================
neo4j:
image: neo4j:2025.10.1
container_name: WeKnora-neo4j
volumes:
- neo4j-data:/data
environment:
- NEO4J_AUTH=${NEO4J_USERNAME:-neo4j}/${NEO4J_PASSWORD:-password}
- NEO4J_apoc_export_file_enabled=true
- NEO4J_apoc_import_file_enabled=true
- NEO4J_apoc_import_file_use__neo4j__config=true
- NEO4JLABS_PLUGINS=["apoc"]
ports:
- "7474:7474" # HTTP 控制台
- "7687:7687" # Bolt 协议
restart: always
networks:
- WeKnora-network
profiles:
- neo4j
- full
# ============================================================
# 12. Qdrant(可选向量数据库)
# 高性能 ANN 检索,启用 profile qdrant
# ============================================================
qdrant:
image: qdrant/qdrant:v1.16.2
container_name: WeKnora-qdrant
ports:
- "${QDRANT_REST_PORT:-6333}:6333"
- "${QDRANT_PORT:-6334}:6334"
volumes:
- qdrant_data:/qdrant/storage
networks:
- WeKnora-network
restart: unless-stopped
profiles:
- qdrant
- full
# ============================================================
# 13. Milvus(可选向量数据库)
# 功能完整,启用 profile milvus
# ============================================================
milvus:
image: milvusdb/milvus:v2.6.11
container_name: WeKnora-milvus
security_opt:
- seccomp:unconfined
command: ["milvus", "run", "standalone"]
environment:
- ETCD_USE_EMBED=true
- ETCD_DATA_DIR=/var/lib/milvus/etcd
- COMMON_STORAGETYPE=local
- DEPLOY_MODE=STANDALONE
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
start_period: 90s
timeout: 20s
retries: 3
ports:
- "19530:19530"
- "9091:9091"
volumes:
- milvus_data:/var/lib/milvus
networks:
- WeKnora-network
restart: unless-stopped
profiles:
- milvus
# ============================================================
# 14. Weaviate(可选向量数据库)
# 轻量级,支持 GraphQL,启用 profile weaviate
# ============================================================
weaviate:
image: semitechnologies/weaviate:1.28.4
container_name: WeKnora-weaviate
environment:
- PERSISTENCE_DATA_PATH=/var/lib/weaviate
- CLUSTER_HOSTNAME=node1
- DEFAULT_VECTORIZER_MODULE=none
- ENABLE_MODULES=none
- AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true
- CLUSTER_GOSSIP_BIND_PORT=7000
- CLUSTER_DATA_BIND_PORT=7001
- RAFT_BOOTSTRAP_EXPECT=1
ports:
- "9035:8080"
- "50052:50051"
volumes:
- weaviate_data:/var/lib/weaviate
networks:
- WeKnora-network
restart: unless-stopped
profiles:
- weaviate
# ============================================================
# 15. Apache Doris(可选 OLAP 向量库)
# FE + BE 单节点,启用 profile doris
# ============================================================
doris-fe:
image: apache/doris:fe-4.1.0
container_name: WeKnora-doris-fe
hostname: doris-fe
environment:
- FE_SERVERS=fe1:doris-fe:9010
- FE_ID=1
ports:
- "${DORIS_FE_HTTP_PORT:-8030}:8030"
- "${DORIS_FE_MYSQL_PORT:-9030}:9030"
volumes:
- doris_fe_meta:/opt/apache-doris/fe/doris-meta
- doris_fe_log:/opt/apache-doris/fe/log
networks:
- WeKnora-network
restart: unless-stopped
profiles:
- doris
doris-be:
image: apache/doris:be-4.1.0
container_name: WeKnora-doris-be
hostname: doris-be
environment:
- FE_SERVERS=fe1:doris-fe:9010
- BE_ADDR=doris-be:9050
depends_on:
- doris-fe
ports:
- "${DORIS_BE_HTTP_PORT:-8040}:8040"
volumes:
- doris_be_storage:/opt/apache-doris/be/storage
- doris_be_log:/opt/apache-doris/be/log
networks:
- WeKnora-network
restart: unless-stopped
profiles:
- doris
# ============================================================
# 16. Dex(可选 OIDC 认证服务)
# 需启用 profile dex 并准备 ./misc/dex-config.yaml
# ============================================================
dex:
image: dexidp/dex:latest
container_name: dex
ports:
- "5556:5556"
volumes:
- ./misc/dex-config.yaml:/etc/dex/config.yaml
command: ["dex", "serve", "/etc/dex/config.yaml"]
profiles:
- dex
- full
# ============================================================
# 17. Langfuse 自建可观测栈(可选)
# 启用 profile langfuse 后启动全套组件(Web + Worker + ClickHouse + MinIO)
# ============================================================
langfuse-db-init:
image: paradedb/paradedb:v0.22.2-pg17
container_name: WeKnora-langfuse-db-init
depends_on:
postgres:
condition: service_healthy
environment:
PGPASSWORD: ${DB_PASSWORD}
entrypoint: ["sh", "-c"]
command:
- |
set -e
echo "[langfuse-db-init] ensuring database '${LANGFUSE_DB_NAME:-langfuse}' exists..."
psql -h postgres -U ${DB_USER} -d postgres -v ON_ERROR_STOP=0 -c "ALTER DATABASE template1 REFRESH COLLATION VERSION;" >/dev/null 2>&1 || true
psql -h postgres -U ${DB_USER} -d postgres -v ON_ERROR_STOP=0 -c "ALTER DATABASE postgres REFRESH COLLATION VERSION;" >/dev/null 2>&1 || true
if psql -h postgres -U ${DB_USER} -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='${LANGFUSE_DB_NAME:-langfuse}'" | grep -q 1; then
echo "[langfuse-db-init] database '${LANGFUSE_DB_NAME:-langfuse}' already exists, skipping."
else
psql -h postgres -U ${DB_USER} -d postgres -v ON_ERROR_STOP=1 -c "CREATE DATABASE \"${LANGFUSE_DB_NAME:-langfuse}\" TEMPLATE template0;"
echo "[langfuse-db-init] database '${LANGFUSE_DB_NAME:-langfuse}' created."
fi
echo "[langfuse-db-init] done."
networks:
- WeKnora-network
restart: "no"
profiles:
- langfuse
- full
langfuse-clickhouse:
image: clickhouse/clickhouse-server:24.8
container_name: WeKnora-langfuse-clickhouse
restart: unless-stopped
user: "101:101"
environment:
CLICKHOUSE_DB: default
CLICKHOUSE_USER: ${LANGFUSE_CLICKHOUSE_USER:-clickhouse}
CLICKHOUSE_PASSWORD: ${LANGFUSE_CLICKHOUSE_PASSWORD:-clickhouse}
volumes:
- langfuse_clickhouse_data:/var/lib/clickhouse
- langfuse_clickhouse_logs:/var/log/clickhouse-server
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:8123/ping || exit 1
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
networks:
- WeKnora-network
profiles:
- langfuse
- full
langfuse-minio:
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
container_name: WeKnora-langfuse-minio
restart: unless-stopped
entrypoint: sh
command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
environment:
MINIO_ROOT_USER: ${LANGFUSE_MINIO_USER:-langfuseminio}
MINIO_ROOT_PASSWORD: ${LANGFUSE_MINIO_PASSWORD:-langfuseminiosecret}
ports:
- "${LANGFUSE_MINIO_S3_PORT:-9100}:9000"
- "${LANGFUSE_MINIO_CONSOLE_PORT:-9101}:9001"
volumes:
- langfuse_minio_data:/data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 5s
timeout: 10s
retries: 5
networks:
- WeKnora-network
profiles:
- langfuse
- full
langfuse-worker:
image: langfuse/langfuse-worker:3
container_name: WeKnora-langfuse-worker
restart: unless-stopped
depends_on: &langfuse-depends-on
langfuse-db-init:
condition: service_completed_successfully
redis:
condition: service_started
langfuse-clickhouse:
condition: service_healthy
langfuse-minio:
condition: service_healthy
entrypoint:
- /bin/sh
- -ec
- |
_enc() { node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$$1"; }
DU=$$(_enc "$$_LF_DB_USER")
DP=$$(_enc "$$_LF_DB_PASSWORD")
RP=$$(_enc "$$_LF_REDIS_PASSWORD")
export DATABASE_URL="postgresql://$$DU:$$DP@postgres:5432/$$_LF_DB_NAME"
export REDIS_CONNECTION_STRING="redis://:$$RP@redis:6379/$$_LF_REDIS_DB"
unset _LF_DB_USER _LF_DB_PASSWORD _LF_REDIS_PASSWORD
exec dumb-init -- ./worker/entrypoint.sh node worker/dist/index.js
environment: &langfuse-env
_LF_DB_USER: ${DB_USER}
_LF_DB_PASSWORD: ${DB_PASSWORD}
_LF_DB_NAME: ${LANGFUSE_DB_NAME:-langfuse}
_LF_REDIS_PASSWORD: ${REDIS_PASSWORD}
_LF_REDIS_DB: ${LANGFUSE_REDIS_DB:-1}
SALT: ${LANGFUSE_SALT:-weknora-langfuse-dev-salt-change-me}
ENCRYPTION_KEY: ${LANGFUSE_ENCRYPTION_KEY:-0000000000000000000000000000000000000000000000000000000000000000}
NEXTAUTH_URL: ${LANGFUSE_NEXTAUTH_URL:-http://localhost:3000}
NEXTAUTH_SECRET: ${LANGFUSE_NEXTAUTH_SECRET:-weknora-langfuse-dev-nextauth-secret-change-me}
TELEMETRY_ENABLED: ${LANGFUSE_TELEMETRY_ENABLED:-false}
LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: "false"
CLICKHOUSE_URL: http://langfuse-clickhouse:8123
CLICKHOUSE_MIGRATION_URL: clickhouse://langfuse-clickhouse:9000
CLICKHOUSE_USER: ${LANGFUSE_CLICKHOUSE_USER:-clickhouse}
CLICKHOUSE_PASSWORD: ${LANGFUSE_CLICKHOUSE_PASSWORD:-clickhouse}
CLICKHOUSE_CLUSTER_ENABLED: "false"
LANGFUSE_S3_EVENT_UPLOAD_BUCKET: langfuse
LANGFUSE_S3_EVENT_UPLOAD_REGION: auto
LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_MINIO_USER:-langfuseminio}
LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_MINIO_PASSWORD:-langfuseminiosecret}
LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: http://langfuse-minio:9000
LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: "true"
LANGFUSE_S3_EVENT_UPLOAD_PREFIX: events/
LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: langfuse
LANGFUSE_S3_MEDIA_UPLOAD_REGION: auto
LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_MINIO_USER:-langfuseminio}
LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_MINIO_PASSWORD:-langfuseminiosecret}
LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT:-http://localhost:9100}
LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: "true"
LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: media/
networks:
- WeKnora-network
profiles:
- langfuse
- full
langfuse-web:
image: langfuse/langfuse:3
container_name: WeKnora-langfuse-web
restart: unless-stopped
depends_on: *langfuse-depends-on
ports:
- "${LANGFUSE_WEB_PORT:-3000}:3000"
entrypoint:
- /bin/sh
- -ec
- |
_enc() { node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$$1"; }
DU=$$(_enc "$$_LF_DB_USER")
DP=$$(_enc "$$_LF_DB_PASSWORD")
RP=$$(_enc "$$_LF_REDIS_PASSWORD")
export DATABASE_URL="postgresql://$$DU:$$DP@postgres:5432/$$_LF_DB_NAME"
export REDIS_CONNECTION_STRING="redis://:$$RP@redis:6379/$$_LF_REDIS_DB"
unset _LF_DB_USER _LF_DB_PASSWORD _LF_REDIS_PASSWORD
if [ -n "$$NEXT_PUBLIC_LANGFUSE_CLOUD_REGION" ]; then
exec dumb-init -- ./web/entrypoint.sh node --import dd-trace/initialize.mjs ./web/server.js --keepAliveTimeout 110000
else
exec dumb-init -- ./web/entrypoint.sh node ./web/server.js --keepAliveTimeout 110000
fi
environment:
<<: *langfuse-env
LANGFUSE_INIT_ORG_ID: ${LANGFUSE_INIT_ORG_ID:-}
LANGFUSE_INIT_ORG_NAME: ${LANGFUSE_INIT_ORG_NAME:-}
LANGFUSE_INIT_PROJECT_ID: ${LANGFUSE_INIT_PROJECT_ID:-}
LANGFUSE_INIT_PROJECT_NAME: ${LANGFUSE_INIT_PROJECT_NAME:-}
LANGFUSE_INIT_PROJECT_PUBLIC_KEY: ${LANGFUSE_INIT_PROJECT_PUBLIC_KEY:-}
LANGFUSE_INIT_PROJECT_SECRET_KEY: ${LANGFUSE_INIT_PROJECT_SECRET_KEY:-}
LANGFUSE_INIT_USER_EMAIL: ${LANGFUSE_INIT_USER_EMAIL:-}
LANGFUSE_INIT_USER_NAME: ${LANGFUSE_INIT_USER_NAME:-}
LANGFUSE_INIT_USER_PASSWORD: ${LANGFUSE_INIT_USER_PASSWORD:-}
networks:
- WeKnora-network
profiles:
- langfuse
- full
# ============================================================
# 18. MCP Server(可选)
# 提供 Model Context Protocol 服务,用于外部工具调用
# ============================================================
mcp:
build:
context: ./mcp-server
container_name: WeKnora-mcp
ports:
- "${MCP_PORT:-8082}:8000"
environment:
- WEKNORA_BASE_URL=http://app:8080/api/v1
- WEKNORA_API_KEY=${WEKNORA_API_KEY:-}
depends_on:
app:
condition: service_healthy
networks:
- WeKnora-network
restart: unless-stopped
profiles:
- full
7、点击立即部署;
8、接下来就是漫长的等待,等待完成。。。
9、访问http://你的NAS_IP:28080 ,选择创建账户进行初始化;

10、输入用户名、邮箱、密码、确认密码,点击注册;

11、此时,有成功的喜悦,也有身心的疲惫,项目就搭建好了!!!

三、注意事项:
安全加固:
注册完成后,将.env文件的 DISABLE_REGISTRATION 改回 true 并重启,以阻止后续公开注册。
DISABLE_REGISTRATION=true
四、使用方法和教程
请参考官网:https://weknora.weixin.qq.com/









