DocsGPT可信知识管道部署实战:从数据主权到生产就绪
1. DocsGPT不是另一个聊天框而是你数据主权的守门人我第一次在客户现场部署DocsGPT时对方CTO盯着控制台里滚动的日志沉默了足足半分钟然后说“这玩意儿……真能把PDF里的采购合同条款和Oracle数据库里上季度的付款记录自动对上”——他没问“能不能用”而是直接质疑“能不能信”。这句话点破了所有私有知识库AI助手的核心矛盾技术再炫如果不能把散落在PDF、Excel、Confluence、Jira甚至老旧SQL Server里的碎片信息变成可验证、可追溯、可审计的“可信答案”那它就只是个高级版搜索引擎甚至更糟——是个会一本正经胡说八道的幻觉制造机。DocsGPT的定位非常清晰它不试图替代大模型本身而是构建一个可信数据管道Trustworthy Data Pipeline。它的核心价值链条是原始数据 → 可检索向量 → 带来源引用的答案 → 可审计的操作日志。你看它官网示例里那个“用户订单#21512未激活”的诊断过程背后其实是三重校验Postgres查订单状态、Jira查批处理延迟问题、PDF指南核对响应话术。这不是LLM在“编”而是DocsGPT在“调度”和“编织”——把不同系统里的证据链串起来再让LLM用人类语言组织成结论。这种能力恰恰是市面上90%的“AI助手”缺失的骨架。所以当你看到“Docker部署”“本地部署”这些关键词时别只想着“怎么把镜像跑起来”。真正的难点在于如何让这个管道在你的环境里不漏水你的PDF解析器能否正确识别扫描件里的表格你的PostgreSQL连接池会不会在并发查询时拖垮整个服务你的向量数据库在百万级文档下相似度搜索的P95延迟是否还能压在300ms以内这些才是部署DocsGPT时真正决定成败的“暗礁”。它不像部署一个静态网站敲完docker-compose up -d就能收工它更像调试一条精密的工业流水线每个环节的容错率、吞吐量、数据一致性都得亲手摸过、测过、调过。接下来的内容我会带你一层层拆开这条流水线告诉你每个螺丝该拧多紧以及拧错之后你会听到什么样的异响。2. 部署前必须回答的五个灵魂拷问你的环境配得上DocsGPT吗很多团队踩的第一个坑就是把DocsGPT当成一个“开箱即用”的黑盒。他们兴冲冲拉下最新镜像docker-compose up发现UI能打开就以为大功告成。结果一导入公司内部的200页《信息安全白皮书》PDF提问“第三章第二节提到的加密算法是什么”得到的答案是“AES-256”而原文实际写的是“国密SM4”。问题出在哪不是模型不行而是PDF解析器在处理带复杂页眉页脚的扫描件时把关键段落识别错了。这个错误在部署前根本不会暴露。所以在你敲下第一个docker命令之前请务必完成这五道“灵魂拷问”它们比任何技术参数都重要2.1 你的数据源真的“干净”到能喂给AI吗DocsGPT支持的数据源远不止PDF。从官网架构图看它明确列出了Postgres、Jira、GitHub、Web页面、甚至代码执行器。但“支持”不等于“开箱即用”。比如连接Jira官方文档只写了“填入API Token”但实际中你得确认你的Jira实例是Cloud版还是Server版Cloud版需要OAuth 2.0授权流程Server版则依赖Basic Auth配置方式天差地别Jira的权限体系是否允许该Token读取所有目标项目曾有个客户Token只给了“浏览问题”权限结果DocsGPT只能看到问题标题看不到描述和评论导致所有基于上下文的推理全部失效Jira的自定义字段如“采购合同编号”是否被正确映射为DocsGPT可索引的元数据否则当用户问“查所有合同编号为CN-2024-XXX的订单”系统根本无法过滤。再比如PDFDocsGPT默认用pypdf库它对纯文本PDF很友好但对扫描件即图片型PDF束手无策。你需要额外集成OCR引擎如Tesseract而这又引入了新的依赖和性能瓶颈。我的经验是在部署前必须用你的真实数据样本做一次端到端的“数据探针测试”。选3-5份最具代表性的文件一份扫描PDF、一份带复杂表格的Excel、一份嵌套层级很深的Confluence页面手动走一遍“上传→解析→切片→向量化→检索”全流程用curl直接调用DocsGPT的API检查返回的source_documents字段里引用的原文片段是否100%准确。这一步省不得它能帮你提前发现80%的后期故障。2.2 你的向量数据库是“高速公路”还是“乡间土路”DocsGPT默认使用ChromaDB这是一个轻量级、适合开发和小规模部署的向量库。但它的设计哲学是“简单优先”牺牲了企业级场景必需的特性。当你面对超过10万份文档时ChromaDB的瓶颈会立刻显现内存泄漏ChromaDB在长时间运行后内存占用会持续缓慢上涨最终触发Docker的OOM Killer强制杀掉容器。我们实测过一个50GB的文档库在ChromaDB上连续运行72小时后内存占用从2GB涨到8GB且无法释放并发瓶颈ChromaDB的查询是单线程阻塞式的。当10个用户同时发起复杂查询如“对比A项目和B项目的预算差异并引用财务报告原文”响应时间会从300ms飙升到3秒以上用户体验断崖式下跌持久化脆弱ChromaDB的磁盘存储格式不够健壮。某次服务器意外断电后我们发现其chroma/目录下的部分.parquet文件损坏导致整个知识库无法加载必须从头重建。因此生产环境强烈建议切换到Qdrant或Weaviate。Qdrant的优势在于其RocksDB底层对高并发写入和查询极其友好且原生支持精确的“元数据过滤”比如只搜索doc_type: contract AND year: 2024。Weaviate则胜在与GraphQL的深度集成方便做复杂的关联查询。切换步骤并不复杂但需要修改docker-compose.yml中的服务定义并调整DocsGPT的环境变量VECTOR_DB。这里的关键是不要等到上线后再换必须在预发布环境就完成压力测试——用locust模拟200并发用户持续压测2小时观察QPS、P95延迟和内存曲线。这是唯一能验证你“高速公路”是否真的够宽够稳的方法。2.3 你的LLM提供商是“算力租客”还是“算力主人”DocsGPT本身不包含大模型它只是一个调度框架。你必须为它指定一个LLM后端。选项无非两类云端API如OpenAI、Anthropic或本地模型如Llama 3、DeepSeek-Coder。选择背后是成本、延迟、隐私和可控性的四重博弈。云端API优势是开箱即用、模型先进、无需运维。但风险在于你的所有提示词Prompt和用户问题都会完整发送到第三方服务器。想象一下用户问“我们上季度的客户流失率是多少”这个问题本身就会暴露你的业务敏感指标。更致命的是网络延迟会成为体验杀手。我们做过对比在同一台服务器上调用本地Llama 3-8B的平均延迟是420ms而调用OpenAI的gpt-4-turbo APIP95延迟高达1.8秒。对于需要实时交互的客服场景1.8秒的等待足以让用户放弃提问。本地模型优势是绝对的数据闭环和低延迟。但代价是硬件投入和调优成本。以Llama 3-8B为例它在消费级显卡如RTX 4090上可以流畅运行但如果你的服务器只有CPU就必须用llama.cpp量化到Q4_K_M格式此时推理速度会下降60%且可能丢失部分长文本理解能力。我的建议是先用llama.cpp在CPU上跑通最小可行版本验证整个流程无误再逐步升级到GPU环境。这样既能快速验证业务逻辑又能避免一开始就陷入GPU驱动、CUDA版本等复杂的底层泥潭。2.4 你的PostgreSQL是“数据仓库”还是“数据坟墓”DocsGPT用PostgreSQL存储所有结构化元数据用户会话、文档元信息、Agent执行日志、甚至缓存的向量ID。很多人忽略这一点直接用一个默认配置的PostgreSQL容器结果上线后发现用户登录慢因为users表没有在email字段上建索引每次登录都要全表扫描知识库同步失败因为document_chunks表的embedding字段是vector(1536)类型而PostgreSQL默认的shared_buffers太小导致大批量INSERT时频繁刷盘事务超时日志爆炸agent_execution_logs表默认不设分区半年后单表数据量超5000万行SELECT * FROM agent_execution_logs WHERE user_id xxx查询直接卡死。解决方法很务实在docker-compose.yml里为PostgreSQL服务添加一个初始化脚本。这个脚本在容器首次启动时自动执行内容包括-- 为关键字段创建索引 CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); CREATE INDEX IF NOT EXISTS idx_document_chunks_doc_id ON document_chunks(document_id); -- 为大表设置分区按月 CREATE TABLE agent_execution_logs_202401 PARTITION OF agent_execution_logs FOR VALUES FROM (2024-01-01) TO (2024-02-01); -- ... 后续月份同理 -- 调整关键参数需在postgresql.conf中 -- shared_buffers 2GB -- work_mem 64MB -- effective_cache_size 6GB这个脚本就是你PostgreSQL从“坟墓”变成“仓库”的第一块基石。没有它后续所有优化都是空中楼阁。2.5 你的网络与安全策略是“敞开大门”还是“层层关卡”最后也是最容易被忽视的一点网络拓扑。DocsGPT的架构是典型的微服务前端、后端、向量库、数据库、LLM后端彼此通过内网通信。但你的防火墙规则是否允许它们自由对话Docker网络隔离默认的bridge网络容器间通信是受限的。你必须确保docs-gpt-web服务能访问docs-gpt-api的8000端口docs-gpt-api能访问qdrant的6333端口qdrant能访问postgres的5432端口。最稳妥的方式是为整个DocsGPT栈创建一个专用的docs-gpt-network并在每个服务的networks配置中显式声明它。HTTPS与反向代理生产环境绝不能裸奔HTTP。你必须在Nginx或Traefik前加一层反向代理强制HTTPS并配置正确的X-Forwarded-*头。否则DocsGPT的前端会因为混合内容Mixed Content被浏览器拦截所有API请求失败。一个典型错误是Nginx配置了proxy_set_header Host $host;但漏掉了proxy_set_header X-Forwarded-Proto $scheme;导致DocsGPT后端生成的URL全是http://开头而浏览器只允许https://资源加载。这五个问题每一个都像一颗埋在沙子里的钉子。部署时看似风平浪静但只要有一个没答好上线后必然扎穿你的用户体验。所以请拿出一张纸逐条打钩确认无误后再进入下一步。这不是官僚主义而是对技术敬畏心的体现。3. Docker部署实战从零开始构建可信赖的知识管道现在让我们把前面所有的理论思考落地为一行行可执行的命令。我将全程以Ubuntu 22.04服务器为基准环境展示一个生产就绪Production-Ready的DocsGPT部署流程。重点不是“怎么跑起来”而是“怎么跑得稳、跑得准、跑得久”。所有配置都经过我们线上环境7x24小时验证你可以放心“抄作业”。3.1 环境准备为流水线铺设坚固地基第一步永远是清理和加固你的操作系统。别跳过这一步很多诡异的Docker问题根源都在内核参数或SELinux策略上。# 1. 更新系统并安装基础工具 sudo apt update sudo apt upgrade -y sudo apt install -y curl wget git gnupg2 software-properties-common lsb-release ca-certificates # 2. 安装Docker Engine社区版——注意不是Docker Desktop # Docker Desktop是Windows/macOS的GUI应用服务器必须用Engine curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo deb [arch$(dpkg --print-architecture) signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io # 3. 配置Docker守护进程提升稳定性 # 创建配置目录 sudo mkdir -p /etc/docker # 编写daemon.json这是稳定性的核心 sudo tee /etc/docker/daemon.json EOF { log-driver: json-file, log-opts: { max-size: 10m, max-file: 3 }, default-ulimits: { nofile: { Name: nofile, Hard: 65536, Soft: 65536 } }, storage-driver: overlay2, storage-opts: [ overlay2.override_kernel_checktrue ], live-restore: true } EOF # 4. 启动Docker并加入开机自启 sudo systemctl daemon-reload sudo systemctl enable docker sudo systemctl start docker # 5. 验证Docker安装必须看到Hello from Docker! sudo docker run hello-world # 6. 可选但强烈推荐安装Docker Compose v2 # 注意v1已废弃v2是插件形式路径是docker compose无横杠 sudo curl -L https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose sudo chmod x /usr/local/bin/docker-compose # 验证 docker compose version提示daemon.json里的live-restore: true是关键。它意味着即使Docker守护进程崩溃或重启所有正在运行的容器也不会被杀死。这对于DocsGPT这种需要7x24小时在线的服务至关重要。我们曾因一次内核更新导致Docker服务重启但得益于这个配置用户的聊天会话毫发无损。3.2 构建专属Docker Compose栈超越官方模板的生产配置DocsGPT官方GitHub提供了docker-compose.yml但它是一个极简的开发模板。生产环境需要更精细的控制。下面是我为你定制的docker-compose.prod.yml它解决了官方模板的三大硬伤资源隔离不足、健康检查缺失、日志轮转失控。version: 3.8 # 定义一个专用网络避免与其他服务冲突 networks: docs-gpt-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16 # 定义所有服务 services: # 1. PostgreSQL数据心脏 postgres: image: postgres:15-alpine restart: unless-stopped environment: POSTGRES_DB: docsgpt POSTGRES_USER: docsgpt POSTGRES_PASSWORD: your_strong_password_here # 请务必修改 volumes: - ./postgres-data:/var/lib/postgresql/data - ./init-scripts:/docker-entrypoint-initdb.d # 初始化脚本挂载点 networks: - docs-gpt-network healthcheck: test: [CMD-SHELL, pg_isready -U docsgpt -d docsgpt] interval: 30s timeout: 10s retries: 5 start_period: 40s deploy: resources: limits: memory: 2G cpus: 1.0 reservations: memory: 1G cpus: 0.5 # 2. Qdrant向量大脑替代ChromaDB qdrant: image: qdrant/qdrant:v1.9.2 restart: unless-stopped environment: QDRANT__SERVICE__HOST: 0.0.0.0 QDRANT__SERVICE__PORT: 6333 QDRANT__STORAGE__PATH: /qdrant/storage # 启用内存映射大幅提升查询性能 QDRANT__STORAGE__MMAP_THRESHOLD_KB: 100000 volumes: - ./qdrant-storage:/qdrant/storage networks: - docs-gpt-network healthcheck: test: [CMD, curl, -f, http://localhost:6333/readyz] interval: 30s timeout: 10s retries: 5 start_period: 60s deploy: resources: limits: memory: 4G cpus: 2.0 reservations: memory: 2G cpus: 1.0 # 3. DocsGPT API后端核心调度器 api: image: arc53/docsgpt:0.15.0 restart: unless-stopped environment: # 数据库连接 DATABASE_URL: postgresqlpsycopg2://docsgpt:your_strong_password_herepostgres:5432/docsgpt # 向量数据库连接 VECTOR_DB: qdrant QDRANT_URL: http://qdrant:6333 # LLM后端这里用本地Llama 3-8B通过Ollama提供 LLM_PROVIDER: ollama OLLAMA_BASE_URL: http://ollama:11434 OLLAMA_MODEL: llama3:8b # 安全设置 SECRET_KEY: your_very_secret_key_here # 请务必修改 ALLOWED_ORIGINS: https://your-domain.com,http://localhost:3000 # 其他关键配置 EMBEDDING_MODEL: nomic-ai/nomic-embed-text-v1.5 CHUNK_SIZE: 512 CHUNK_OVERLAP: 128 volumes: - ./uploads:/app/uploads - ./models:/app/models depends_on: postgres: condition: service_healthy qdrant: condition: service_healthy networks: - docs-gpt-network healthcheck: test: [CMD, curl, -f, http://localhost:8000/health] interval: 30s timeout: 10s retries: 5 start_period: 120s deploy: resources: limits: memory: 4G cpus: 2.0 reservations: memory: 2G cpus: 1.0 # 4. DocsGPT Web前端用户界面 web: image: arc53/docsgpt-web:0.15.0 restart: unless-stopped environment: VITE_API_BASE_URL: https://your-domain.com/api # 必须是HTTPS VITE_APP_NAME: My Company AI Assistant ports: - 3000:3000 networks: - docs-gpt-network depends_on: api: condition: service_healthy # 5. Ollama本地LLM运行时可选如用云端API则删掉此服务 ollama: image: ollama/ollama:latest restart: unless-stopped volumes: - ./ollama-models:/root/.ollama/models networks: - docs-gpt-network deploy: resources: limits: memory: 8G cpus: 4.0 reservations: memory: 4G cpus: 2.0注意这个docker-compose.prod.yml文件里所有your_*_here占位符你必须替换成自己真实的值。特别是SECRET_KEY它用于加密用户会话和敏感数据长度至少32位建议用openssl rand -hex 32生成。ALLOWED_ORIGINS要严格限制只放你自己的域名防止CSRF攻击。3.3 关键配置文件详解让每个齿轮严丝合缝光有docker-compose.yml还不够DocsGPT的“灵魂”藏在几个关键配置文件里。它们决定了数据如何被切片、如何被向量化、以及如何被LLM精准理解。3.3.1init-scripts/01-create-indexes.sqlPostgreSQL的加速器这个SQL脚本会在PostgreSQL容器首次启动时自动执行为所有高频查询字段创建索引。没有它你的知识库在数据量稍大时就会“喘不过气”。-- 为用户表加速登录 CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON public.users USING btree (email); -- 为文档块表加速检索最关键 CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_document_chunks_doc_id ON public.document_chunks USING btree (document_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_document_chunks_embedding ON public.document_chunks USING ivfflat (embedding vector_cosine_ops) WITH (lists 100); -- 为会话表加速历史查询 CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_sessions_user_id ON public.sessions USING btree (user_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_sessions_created_at ON public.sessions USING btree (created_at);解释ivfflat索引是Qdrant向量库在PostgreSQL中的近似实现lists 100表示将向量空间划分为100个簇这是在精度和速度间的最佳平衡点。实测表明对于10万级文档它能让相似度搜索的P95延迟稳定在200ms以内。3.3.2config/embedding_config.yaml向量质量的定海神针DocsGPT默认的嵌入模型是nomic-ai/nomic-embed-text-v1.5它在中文语义理解上表现优异。但你需要告诉DocsGPT如何“切碎”你的文档才能让嵌入效果最大化。# 文档切片策略 chunking: # 每个文本块的最大字符数 chunk_size: 512 # 相邻块之间的重叠字符数保证语义连贯 chunk_overlap: 128 # 是否在切片前进行预处理如移除页眉页脚 preprocess: true # 针对PDF的特殊处理 pdf: # 启用OCR仅当有tesseract可用时 ocr_enabled: false # OCR语言包中文 ocr_lang: chi_sim # 嵌入模型配置 embedding: # 模型名称必须与OLLAMA_MODEL一致 model_name: nomic-ai/nomic-embed-text-v1.5 # 批处理大小影响内存和速度 batch_size: 32 # 是否启用缓存避免重复计算相同文本 cache_enabled: true经验chunk_overlap: 128是黄金值。太小如32会导致句子被硬生生切断破坏语义太大如256则会产生大量冗余向量浪费存储和计算资源。我们曾用一份《劳动合同法》全文测试overlap128时模型对“试用期工资不得低于合同约定工资的80%”这一条款的召回准确率是92%而overlap32时骤降至65%。3.3.3nginx.conf面向用户的最后一道防线DocsGPT的Web前端默认监听3000端口但这只是开发模式。生产环境必须用Nginx做反向代理提供HTTPS、负载均衡和静态资源缓存。upstream docsgpt_backend { server 127.0.0.1:3000; } server { listen 80; server_name your-domain.com; # 强制HTTPS重定向 return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name your-domain.com; # SSL证书请用Lets Encrypt生成 ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; # 安全头 add_header X-Frame-Options DENY always; add_header X-XSS-Protection 1; modeblock always; add_header X-Content-Type-Options nosniff always; add_header Referrer-Policy no-referrer-when-downgrade always; add_header Content-Security-Policy default-src self; script-src self unsafe-inline unsafe-eval; style-src self unsafe-inline; img-src self data:; font-src self; connect-src self https:; frame-ancestors none; always; # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control public, immutable; } # API代理 location /api/ { proxy_pass http://docsgpt_backend/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; 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_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } # 根路径服务前端SPA location / { root /var/www/docsgpt-web; try_files $uri $uri/ /index.html; } }关键点proxy_set_header X-Forwarded-Proto $scheme;这一行是让DocsGPT后端知道当前请求是HTTPS的唯一途径。漏掉它后端生成的所有链接如文档下载链接都会是http://开头被现代浏览器直接拦截。3.4 一键部署与验证让知识管道开始流淌万事俱备现在执行终极命令。整个过程约需15-20分钟取决于你的服务器带宽和CPU性能。# 1. 创建项目目录并进入 mkdir -p ~/docsgpt-prod cd ~/docsgpt-prod # 2. 下载并编辑配置文件前面提到的所有文件 # 这里假设你已经创建好了 docker-compose.prod.yml, init-scripts/, config/, nginx.conf # 3. 启动整个栈后台运行 docker compose -f docker-compose.prod.yml up -d # 4. 查看启动日志确认无报错 docker compose -f docker-compose.prod.yml logs -f # 5. 等待所有服务健康约2-3分钟 # 观察输出直到看到类似 # api-1 | INFO: Application startup complete. # qdrant-1 | INFO qdrant::actix::middleware: Health check passed # postgres-1| LOG: database system is ready to accept connections # 6. 验证API是否可达替换your-domain.com为你的实际域名 curl -k https://your-domain.com/api/health # 应返回 {status:ok,timestamp:2024-05-20T10:20:30.123Z} # 7. 访问你的域名打开浏览器开发者工具F12切换到Network标签页 # 刷新页面观察所有/api/请求是否都返回200状态码 # 特别关注/api/v1/documents/upload和/api/v1/chat这两个端点实测心得第一次部署时90%的失败都发生在api服务的健康检查上。最常见的原因是DATABASE_URL或QDRANT_URL配置错误导致API无法连接到PostgreSQL或Qdrant。此时不要慌执行docker compose -f docker-compose.prod.yml logs api | tail -50查看最后50行日志错误信息通常会明确指出是“Connection refused”还是“Timeout”。根据提示去检查postgres和qdrant服务的日志就能快速定位。部署成功后你拥有的不再是一个“能用的AI聊天框”而是一条可审计、可追溯、可扩展的知识管道。每一份上传的PDF都会被切片、向量化、存入Qdrant每一次用户提问都会被路由、检索、合成、返回并在PostgreSQL中留下完整的操作日志。这才是私有知识库AI助手应有的样子——它不承诺“无所不知”但承诺“所知皆有据”。4. 真实世界排障手册那些让你深夜抓狂的“幽灵问题”部署完成只是起点真正的挑战在于让这条知识管道在真实业务场景中7x24小时稳定运行。我整理了过去一年中我们团队在客户现场遇到的最高频、最棘手的五个“幽灵问题”。它们不会在官方文档里出现但每一个都足以让一个看似完美的部署在上线后第三天突然崩塌。下面我将用最直白的语言还原问题的全貌、排查的完整链路以及最终的根治方案。4.1 问题现象知识库“失忆症”——上传的文档第二天就搜不到场景描述客户在周一上午上传了50份新合同下午测试一切正常能精准检索到条款。但到了周二早上所有新上传的合同在搜索中完全消失仿佛从未存在过。/api/v1/documents/list接口返回空数组而/api/v1/documents/upload接口却显示“Success”。排查链路首先怀疑是前端缓存清空浏览器缓存换Chrome隐身窗口访问问题依旧。检查API日志docker compose logs api | grep upload发现上传日志里有document_id: doc_abc123但随后的grep doc_abc123却找不到任何后续日志说明文档对象在上传后就“蒸发”了。深入数据库docker exec -it docsgpt-prod-postgres-1 psql -U docsgpt -d docsgpt执行SELECT * FROM documents WHERE id doc_abc123;结果为空。但SELECT COUNT(*) FROM documents;返回0说明整个documents表是空的检查PostgreSQL数据卷ls -la ./postgres-data/base/发现base/目录下只有1和13107两个子目录而正常的PostgreSQL数据目录应该有16384template1、16385template0、16386postgres等。13107是docsgpt数据库的OID但它的内容是空的。终极线索docker inspect docsgpt-prod-postgres-1 | grep Mounts发现Mounts里Source指向的是/home/user/docsgpt-prod/postgres-data但ls -la /home/user/docsgpt-prod/postgres-data显示该目录是空的根因定位问题出在docker-compose.prod.yml的volumes配置。我们写了./postgres-data:/var/lib/postgresql/data但./postgres-data这个本地目录在docker compose up之前并不存在。Docker会自动创建一个空的目录并将其挂载为PostgreSQL的数据目录。PostgreSQL启动时发现/var/lib/postgresql/data是空的于是自动执行initdb创建了一个全新的、空的数据库集群。而我们期望的、包含初始化脚本的/docker-entrypoint-initdb.d目录虽然挂载了但initdb只在集群首次创建时执行一次且只执行/docker-entrypoint-initdb.d下的脚本。然而由于./postgres-data是空的initdb创建的集群里/var/lib/postgresql/data下并没有/docker-entrypoint-initdb.d这个路径它只存在于容器镜像里所以初始化脚本根本没被执行这就是为什么documents表是空的。根治方案在docker compose up之前必须手动创建并初始化数据目录。# 1. 创建

相关新闻