
在这个信息爆炸的时代,我们每天都会浏览大量的技术文章、新闻资讯和灵感素材。传统的书签管理工具(如 Pocket、Cubox)虽然好用,但存在两个致命痛点:
为了解决这些问题,我决定利用手头的 Ubuntu NAS 和一台搭载 RTX 4070 Super 的 Windows 主机,搭建一套完全私有化、利用本地算力进行智能分类的知识库系统 —— KaraKeep(基于 Hoarder 开发的复刻版)。
这一路走来,从 Docker 镜像被墙、数据库权限报错,到跨平台 AI 服务的连通性问题,我踩遍了所有的坑。本文将用最详细的笔墨,还原整个部署与排错过程,手把手教你搭建这套“梦中情库”。
在开始之前,我们需要理清拓扑结构。这不仅仅是装个软件,而是涉及到跨设备的网络通信。
服务端 (Brain): Ubuntu Server NAS
运行 Docker Compose 编排 KaraKeep 及其依赖服务(Redis, MeiliSearch, Chrome)。
网络环境:国内家庭宽带,已部署 v2raya 作为透明网关/代理(端口 20172)。
算力端 (Muscle): Windows PC
硬件:NVIDIA RTX 4070 Super (12GB 显存)。
软件:Ollama,运行 DeepSeek-R1 或 Qwen2.5 模型。
IP 地址:10.10.158.165(局域网静态 IP)。
国内环境下,docker pull 直接拉取 gcr.io (Google) 或 ghcr.io (GitHub) 的镜像几乎 100% 失败。我们需要给 Docker 引擎配置一个全局代理,让它能通过 v2raya “出国”去下载镜像。
注意: 这里的配置只影响 Docker 下载镜像 的行为,不会 影响容器运行起来后的内部网络(容器内部网络我们稍后单独配置)。
请通过 SSH 登录 NAS,执行以下操作:
bashsudo mkdir -p /etc/systemd/system/docker.service.d
HTTP_PROXY 环境变量。特别注意 NO_PROXY,我们需要确保 Docker 连接本机和阿里云等国内镜像源时不走代理,避免绕路。bashsudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
# 代理地址指向你的 v2raya 端口
Environment="HTTP_PROXY=http://127.0.0.1:20172"
Environment="HTTPS_PROXY=http://127.0.0.1:20172"
# 直连名单:本机、阿里云镜像源、网易源等
Environment="NO_PROXY=localhost,127.0.0.1,::1,.aliyuncs.com,.daocloud.io,.mirror.aliyuncs.com"
EOF
bashsudo systemctl daemon-reload sudo systemctl restart docker
sudo docker info | grep Proxy,如果你看到了你的代理 IP,说明 Docker 已经具备了“全球购”的能力。这是官方文档通常不会细说,但 NAS 用户最容易“翻车”的地方。
no such table: user?很多用户在初次部署后,注册用户网页报错 500,日志提示 no such table: user。这是因为 KaraKeep 容器内部默认使用 UID 1000 的用户身份运行,出于安全考虑,它没有 root 权限。
如果你在 NAS 上用 root 账号创建了挂载目录(./data),容器里的进程就没有权限写入数据库文件。结果就是:容器启动了,但数据库初始化脚本(Migration)失败了,留下一个空的数据库文件。
为了彻底杜绝权限问题,我们必须手动创建目录并移交所有权。
bash# 1. 进入你的部署目录
cd /opt/stacks/karakeep
# 2. 如果之前运行失败过,先清理残留(慎用,仅限新部署)
sudo docker-compose down
sudo rm -rf ./data
# 3. 手动创建三个核心挂载目录
mkdir -p data redis meili_data
# 4. 【核心步骤】将目录所有权移交给用户 1000
# 这一步是容器能否正常读写的关键
sudo chown -R 1000:1000 .
我们需要一份针对中国大陆网络环境 + NAS 存储习惯深度定制的配置文件。
.env 文件这个文件控制着整个系统的“神经中枢”。除了常规配置,我们重点关注 存储路径纠正 和 AI 本地化。
请在同级目录下创建 .env 文件:
bash# ==============================
# 🔐 安全与基础配置
# ==============================
# 必须设置随机密钥,否则报错 NO_SECRET
NEXTAUTH_SECRET=Jd83kd920djd823jd92j0d9j2d09j2d_SuperSecret
# 搜索服务的密钥,随便填
MEILI_MASTER_KEY=MySearchKey123456
# 你的 NAS 局域网访问地址 (务必填 IP,不要填 localhost)
NEXTAUTH_URL=http://10.10.158.160:3000
# ==============================
# 📂 存储路径修正 (填坑重点)
# ==============================
# 官方默认将数据存在容器内部深处。
# 我们必须显式告诉程序:“把数据写到 /data 去!”
# 这样配合 Docker 的挂载,数据才能真正保存到 NAS 硬盘上。
DATA_DIR=/data
# ==============================
# 🤖 本地 AI 与 汉化配置
# ==============================
# 强制 AI 用简体中文输出标签和摘要
INFERENCE_LANG="Simplified Chinese"
# 指向局域网内的 Windows 电脑 (Ollama)
OLLAMA_BASE_URL=http://10.10.158.165:11434
# 模型名称 (推荐 DeepSeek-R1 或 Qwen2.5)
INFERENCE_TEXT_MODEL=r1
# 上下文窗口大小
INFERENCE_CONTEXT_WINDOW=4096
# 如果只用 Ollama,OpenAI Key 留空即可
OPENAI_API_KEY=""
# --- 核心依赖服务连接 ---
# 告诉系统搜索引擎的内部容器地址
MEILI_ADDR=http://meilisearch:7700
# 告诉系统无头浏览器的内部容器地址
BROWSER_WEB_URL=http://chrome:9222
# ==============================
# 🌐 容器网络代理 (爬虫专用)
# ==============================
# 让 KaraKeep 容器内部可以通过代理去爬取被墙的网页
HTTP_PROXY=http://10.10.158.160:20172
HTTPS_PROXY=http://10.10.158.160:20172
# 【至关重要】NO_PROXY 白名单
# 务必把 Ollama 的 IP (10.10.158.165) 加进去!
# 否则容器会尝试通过代理去连局域网 AI,导致 "fetch failed" 错误。
NO_PROXY=localhost,127.0.0.1,::1,chrome,meilisearch,10.10.158.165
# ==============================
# ⚙️ 其他功能开关
# ==============================
# 注册期间设为 false,注册完改成 true
DISABLE_SIGNUPS=false
# 开启全网页长截图
CRAWLER_FULL_PAGE_SCREENSHOT=true
docker-compose.yml此处我们替换了 Chrome 镜像,因为官方的 gcr.io 镜像在国内极难拉取。
yamlversion: "3.8"
services:
web:
image: ghcr.io/karakeep-app/karakeep:release
container_name: karakeep_web
restart: unless-stopped
volumes:
# 【绑定挂载】数据直接在当前文件夹可见,方便备份
- ./data:/data
ports:
- 3000:3000
env_file:
- .env
depends_on:
- redis
- meilisearch
- chrome
redis:
image: redis:7.2-alpine
container_name: karakeep_redis
restart: unless-stopped
volumes:
- ./redis:/data
chrome:
# 【优化】使用 Docker Hub 的镜像源,避免 gcr.io 拉取失败
image: zenika/alpine-chrome:124
container_name: karakeep_chrome
restart: unless-stopped
command:
- --no-sandbox
- --disable-gpu
- --disable-dev-shm-usage
- --remote-debugging-address=0.0.0.0
- --remote-debugging-port=9222
- --hide-scrollbars
meilisearch:
image: getmeili/meilisearch:v1.11.1
container_name: karakeep_meili
restart: unless-stopped
env_file:
- .env
environment:
- MEILI_NO_ANALYTICS=true
volumes:
- ./meili_data:/meili_data
这是整个部署中最具挑战性的一环。我们需要让 Linux 容器里的应用,跨越设备去调用 Windows 上的显卡算力。
TypeError: fetch failed在配置好一切后,我们查看日志,发现 AI 任务频繁失败:
[inference] inference job failed: TypeError: fetch failed
这说明网络不通。排查思路如下:
HTTP_PROXY,代理服务器不知道 10.10.158.165 是谁,拒绝了请求。.env 的 NO_PROXY 里加上该 IP。127.0.0.1,拒绝来自外部的连接。请在运行 4070 Super 的那台 Windows 电脑上操作:
OLLAMA_HOST0.0.0.0
(这代表监听所有网络接口)不要盲目重启容器,我们先在 NAS 终端里进行一次“外科手术式”的测试。
bash# 使用 wget 命令,从容器内部去探测 Ollama
# 如果返回 "Ollama is running",说明路通了!
sudo docker exec karakeep_web wget -qO- http://10.10.158.165:11434
一切准备就绪,激动人心的时刻到了。
bash# 启动所有服务
sudo docker-compose up -d
# 强烈建议实时查看日志,观察 AI 是否开始工作
sudo docker-compose logs -f web
向 KaraKeep 中丢入一个知乎或技术博客的链接。几秒钟后,观察日志:
Taking screenshot... (Chrome 正在离线归档)Starting inference worker... (请求发送给 4070S)[Inference] Successfully annotated item...此时刷新网页,你会发现文章卡片下自动出现了 #人工智能 #技术分析 等精准的中文标签。
通过这次折腾,我们不仅获得了一个强大的书签管理工具,更深入理解了 Docker 的网络模型、Linux 的权限管理以及跨平台的 AI 服务集成。
这套方案的优势在于:
/data 目录下,可见可备份。这就是 HomeLab 的魅力所在 —— 折腾,然后掌控一切。希望这篇教程能成为你搭建私人知识库的最后一块拼图!
本文作者:小转圈
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!