Open WebUI 免 Docker 怎么装:首启 4 分 17 秒卡在哪

Open WebUI 不用 Docker 也能装,两条命令,服务 13 秒起来。前提是把默认的 HuggingFace 全量下载关掉:默认配置下首次启动会静默下载 919MB,实测 4 分 17 秒才监听端口。下面所有数字来自 macOS 上的 Python 安装实测,版本 0.13.3。

先算清这台机器的账

装之前先看占用。Python 依赖的体量是这套方案最容易低估的部分,torch 与 transformers 一进来就过 1.9GB,比很多桌面客户端还大。

项目 实测值 说明
虚拟环境体积 1.9 GB 242 个包,含 torch 2.15.0、transformers 5.5.4、chromadb 1.5.9
安装耗时 28 秒 uv 加清华源,含解释器下载 1.04 秒
首次启动 257 秒 其中 207 秒在下载嵌入模型
首次启动(关掉 HF 下载) 13 秒 空数据目录,含 72 条建表迁移
热重启 14 秒 数据目录已存在,迁移全部跳过
常驻内存 745 MB 空载 RSS,无对话无知识库
默认监听 0.0.0.0:8080 同网段可直接访问

内存这一项要配合模型一起算。前端 745MB 只是网页服务本身,真正的显存在 Ollama 那边,8B 模型的账可以按 本地大模型显存怎么算 里的公式估。

两条命令装完

Open WebUI 只支持 Python 3.11 与 3.12。3.13 以上没有可用轮子,装到一半会报找不到匹配发行版。用 uv 拉一个 3.11 解释器最快,实测 1.04 秒。

uv python install 3.11
uv venv --python 3.11 .venv
UV_DEFAULT_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple uv pip install --python .venv/bin/python open-webui

第三行把索引变量写在命令前面,只对这一次生效,不会污染 shell。走默认 PyPI 要等好几分钟,清华源 28 秒装完 242 个包。

查版本别用 python -c "import open_webui; print(open_webui.__version__)",这个模块没有该属性,会直接报错。用 metadata 那一路:

.venv/bin/python -c "from importlib.metadata import version; print(version('open-webui'))"

首启日志读到哪一步就该等

启动顺序固定,认准几个标志就不会把正常等待当成卡死。

第一行打印密钥来源。不带 WEBUI_SECRET_KEY 时它会现场生成 32 字节,写到当前工作目录的 .webui_secret_key。紧接着是几十条 alembic 迁移,空库首次建表实测 72 条,从 7e5b5dc7342b 走到最新版本,滚动很快,不会停留。

迁移跑完会出现一行 CORS 警告,提示 * 不适合生产环境。这行之后如果没有新的输出,官方排障文档把这种现象归为启动挂起,真正原因多数是下一个动作:下载嵌入模型。

默认嵌入引擎是本地 SentenceTransformers,模型固定为 all-MiniLM-L6-v2。日志里会出现 Fetching 30 files 的进度条,之后才加载权重、起 uvicorn。判断服务到底能不能用,别看日志末尾,直接探端口:

lsof -nP -iTCP:8080 -sTCP:LISTEN
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/

返回 200 才算起来。返回 000 说明端口还没监听,进程在忙别的事,继续等。这套判断方法比翻日志可靠,日志里的进度条会被回车符覆盖,复制出来经常只剩最后一行。

把首启从四分十七秒压到十三秒

那 30 个文件不是 30 个小文件。实测缓存目录长到 919MB,原因是仓库里同一套权重有四个框架版本,全部被拉了下来:tf_model.h5 91.0MB、pytorch_model.bin 90.9MB、rust_model.ot 90.9MB、model.safetensors 90.9MB。实际加载的只有最后一个,前三份纯属陪跑。

三件事一起做,启动就干净了。嵌入交给本地 Ollama,HF 目录给个空路径,同时禁止联网回源。

export DATA_DIR=/Users/you/owui/data
export HF_HOME=/Users/you/owui/hf
export HF_HUB_OFFLINE=1
export RAG_EMBEDDING_ENGINE=ollama
export RAG_EMBEDDING_MODEL=qwen3-embedding:0.6b
open-webui serve --port 8080
启动条件 端口可访问耗时 HF 缓存占用 日志特征
默认配置,空数据目录 257 秒 919 MB 出现 Fetching 30 files 进度条
关掉 HF 并把嵌入交给 Ollama 13 秒 0 字节 无 Fetching,迁移完直接监听
同配置热重启 14 秒 0 字节 迁移全部跳过

同一台机器、空数据目录,这套配置 13 秒监听端口,HF 目录 0 字节,日志里一条 Fetching 都没有。代价是知识库的向量化改成调 Ollama:实测往知识库加一个文本文件后,ollama ps 里立刻多出 qwen3-embedding:0.6b,占用 1.2GB 显存,全部跑在 GPU 上。

HF_HUB_OFFLINE=1 在这里不冒险。它只影响 transformers 一侧的联网行为,Ollama 走的是另一条 HTTP 通道,不受限制。要是哪天想用回本地嵌入模型,把这个变量去掉、再让 HF_ENDPOINT 指向国内镜像即可。

嵌入模型怎么选、维度混用会出什么问题,Cherry Studio 知识库配嵌入 那篇有同机实测,两套前端用的是同一个 Ollama 接口,结论可以直接搬。分块长度受上下文限制,细节见 Ollama 上下文怎么设。

8080 端口和局域网访问

open-webui serve --help 只给两个参数:--host 默认 0.0.0.0,--port 默认 8080。其余全部走环境变量,命令行改不了数据目录,这一点和很多 CLI 的习惯不同。

8080 是重灾区。本机这个端口被 nginx 占着,Open WebUI 会一路跑到最后一步才报错,然后进程直接退出:

[Errno 48] error while attempting to bind on address ('0.0.0.0', 8080): address already in use

报错出现在加载完嵌入模型之后,前面几十秒的等待全部白费。启动前先 lsof -nP -iTCP:8080 -sTCP:LISTEN 看一眼,比事后翻日志快得多。

默认绑 0.0.0.0 意味着同网段手机能直接打开,首次访问时会让你注册,第一个账号自动成为管理员。只想本机用就加 --host 127.0.0.1。注册完记得把 ENABLE_SIGNUP 关掉,否则同一网段的人都能自己开号。

数据目录与密钥不在一个地方

数据库、上传文件、向量库都在 DATA_DIR 下,默认取当前目录的 data。密钥文件 .webui_secret_key 却写在启动时的工作目录,跟 DATA_DIR 无关。这个区别会让人莫名掉登录。

实测过程是这样的:同一份 DATA_DIR,换到另一个目录启动,账号密码照样能登进去,说明数据库读到了;但换目录之前拿到的 token 打接口直接 401。原因是新目录生成了新的 32 字节密钥,旧签名全部作废。

迁移时把数据目录和工作目录一起搬,或者在启动脚本里显式给 WEBUI_SECRET_KEY,两头都省事。反过来说,忘了数据目录放在哪也能靠这个文件定位:启动日志第一行就写着它的绝对路径。

磁盘清理的思路和模型目录一样,先量体积再动路径,参考 Ollama 模型占 C 盘 里的做法。Open WebUI 自己的占用很小,数据目录 1.1MB 起步,真正吃盘的是 .venv 和 HF 缓存。

接 Ollama:环境变量只写一次库

Ollama 在本机 11434 上跑着的话,装完不用配。登录后模型列表直接就是本地那几个,/api/models 返回 5 个条目,owned_by 全是 ollama。

要指到别的机器,变量名是复数的 OLLAMA_BASE_URLS,值是 URL 数组。实测全新数据目录首次启动时,单数写法 OLLAMA_BASE_URL 也会被读进去,落库后 /ollama/config 返回的就是新地址。

坑在第二次。这套配置是首次初始化时写进数据库的,之后以库里的值为准。用同一个数据目录重启,传 OLLAMA_BASE_URL=http://127.0.0.1:11500,接口返回的仍然是 http://localhost:11434,环境变量被彻底无视。改地址只有两条路:管理面板里的连接设置,或者换一个空数据目录重来。

用另一台机器跑模型时,Ollama 侧要设 OLLAMA_HOST=0.0.0.0,否则本机通了远端不通,前端只会显示模型列表为空,不给任何提示。

三处会浪费半小时的现场

第一处,回复是空的,但 token 已经烧完。用 qwen3:8b 提一个只要求两个字的请求,max_tokens 分别给 20、50、300,三次正文都是空串,output_tokens 每次都恰好等于上限。把上限提到 600 才吐出「能用」,此时 output_tokens 是 265,其中 reasoning_content 占了 457 个字符,整段思考耗时 13.5 秒。判据很硬:看 output_tokens 是否等于上限,等于就是被思考链吃光了。实测在 OpenAI 兼容端点上传 "think": false 无效,在提示词里加 /no_think 也无效,唯一可靠的办法是把上限放大到 512 以上。

第二处,知识库查不到东西。调检索接口时 collection_names 要填知识库 id,填成 file_id 不报错,直接返回三个空数组,让人以为嵌入没成功。填对之后同一条查询立刻命中,距离 0.79。

第三处,端口被占的报错来得太晚。前面已经说过,这里只补操作顺序:先探端口,再启服务,最后才看日志。

常见问题

不用 Docker 会缺功能吗。不会。对话前端、知识库、模型连接都来自同一个 Python 包,Docker 镜像只是把这套依赖封在容器里。差别在隔离方式,pip 装法把 1.9GB 依赖放在你指定的虚拟环境,谁也污染不了谁。

官方推荐 Docker,为什么还写 pip 这一套。没有 Docker 的机器、或者只想临时试两天的场景,pip 更省事,一条命令就能卸干净。已经装了 Docker Desktop 的话,官方镜像仍是首选,能避开本文大半的路径问题。

升级会不会丢数据。数据都在 DATA_DIR 里,升级只换包。命令是 uv pip install --upgrade --python .venv/bin/python open-webui,升完先确认 .webui_secret_key 没换位置,否则所有人要重新登录一次。