DOCAT Ubuntu 22.04 安装部署指南(nginx + systemd 实测)
在 Ubuntu 22.04 上按官方源码路径部署 DOCAT 1.6.1:Python venv 后端 + Node 构建前端 + systemd 服务化 + nginx 反代(端口 8143),含 MkDocs 文档上传全链路验证、4 个排障实录与 k8s 路径说明,全部命令与回显真机实测。
DOCAT Ubuntu 22.04 安装部署指南(nginx + systemd 实测)
本文在 Ubuntu 22.04 服务器上按官方源码路径完整部署 DOCAT 1.6.1(官方最新稳定版,发布标签提交于 2026-09-10,查询日期 2026-10-28),部署形态为生产推荐形态:nginx 托管前端与文档静态文件 + uvicorn 常驻 API 服务(systemd 托管),Web 服务端口使用 8143。文中所有命令与回显均为真实服务器上的实测记录,可直接照抄执行。
环境基线与最终状态:
| 项 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04(Python 3.10.12 系统自带) |
| DOCAT 版本 | 1.6.1(源码标签安装,pip 包版本号显示 0.0.0 为上游 pyproject 占位,属正常现象) |
| 关键依赖 | fastapi 0.162.0 / uvicorn 0.54.0 / tinydb 4.9.0 / python-magic 0.4.27 / python-multipart 0.0.32 |
| 前端构建 | Node v24.22.1 + yarn 1.22.22(仅构建期需要) |
| Web 端口 | 8143(nginx 对外),127.0.0.1:5000(uvicorn,仅本机监听) |
| 存储根目录 | /var/docat(属主 www-data) |
相关阅读:《DOCAT 介绍与选型指南》、《DOCAT 配置参数详解》、《DOCAT 常用 CLI 命令详解》。
一、部署架构
DOCAT 官方源码自带 nginx 配置模板(仓库内 docat/nginx/default),其预期部署形态是:
浏览器 ──> nginx :8143
├── / → /var/www/html (前端 SPA 静态文件)
├── /doc/... → /var/docat/doc/... (上传的文档,静态文件直出)
└── /api/... → 127.0.0.1:5000 (uvicorn 运行的 FastAPI 后端)
需要提前准备的组件清单:
- nginx:托管前端产物、文档静态文件,并把 /api 反代到后端;
- Python 3.10+ 与 venv:运行后端 API;
- libmagic1:python-magic 的系统库依赖(项目图标上传时的文件类型识别依赖它,缺装会导致图标接口 500);
- Node.js 20.19+ 与 yarn:仅在构建前端阶段需要,构建完成后可卸载;
- unzip/zip:后端解包上传的 zip 需要(unzip 属 libmagic 之外的常规工具,zip 用于制作上传测试包)。
二、安装系统依赖
# apt-get update
# export DEBIAN_FRONTEND=noninteractive
# apt-get install -y python3.10 python3.10-venv python3-pip nginx libmagic1 git curl unzip zip
实测回显(节选):
Setting up python3.10-venv ...
Setting up nginx ...
Processing triggers for man-db ...
安装完成后验证:
# python3 --version
Python 3.10.12
# nginx -v
nginx version: nginx/1.18.0 (Ubuntu)
三、获取 DOCAT 1.6.1 源码
从官方仓库拉取 1.6.1 标签(服务器需可访问 github.com,国内网络可自行配置代理环境变量后执行):
# export https_proxy=http://<代理地址>:<端口>
# git clone --depth 1 --branch 1.6.1 https://github.com/docat-org/docat.git /opt/docat-src
# ls /opt/docat-src
CONTRIBUTING.md Dockerfile LICENSE README.md doc docat web
目录说明:docat/ 是 Python 后端(FastAPI 应用包),web/ 是 React 前端源码,doc/ 内含前端构建时需要嵌入的帮助页素材。
四、安装后端 API
用 venv 隔离安装后端(pip 会按官方 docat/pyproject.toml 自动解析依赖):
# python3 -m venv /opt/docat-venv
# /opt/docat-venv/bin/pip install /opt/docat-src/docat
安装完成后验证应用可导入:
# /opt/docat-venv/bin/python -c 'from docat.app import app; print("docat.app import OK")'
docat.app import OK
# /opt/docat-venv/bin/pip show docat | grep -E '^(Name|Version)'
Name: docat
Version: 0.0.0
版本号显示 0.0.0 是上游 pyproject.toml 中的占位写法(官方以 git 标签管理版本),不影响功能。
五、构建前端
前端是 React + Vite 工程,构建产物是纯静态文件。官方构建约定有两个必须遵守的细节(都在官方 Dockerfile 构建脚本中体现):
- 构建时注入环境变量
VITE_DOCAT_VERSION,前端页面底部会显示该版本号; - 把仓库
doc/getting-started.md拷贝到web/src/assets/,前端帮助页直接引用该文件。
# apt-get install -y nodejs yarn # 需 Node.js >= 20.19(本文实测 v24.22.1)
# cp -r /opt/docat-src/web /opt/web-build
# cp /opt/docat-src/doc/getting-started.md /opt/web-build/src/assets/
# cd /opt/web-build
# export VITE_DOCAT_VERSION=1.6.1
# yarn install --frozen-lockfile
# yarn build
yarn build 实测回显(节选):
yarn run v1.22.22
$ tsc && vite build
vite v8.2.2 building client environment for production...
transforming...
✓ 11752 modules transformed.
dist/assets/index-Bs-JyvES.css 32.12 kB │ gzip: 6.38 kB
dist/assets/index-BmH91sRv.js 771.38 kB │ gzip: 242.14 kB
✓ built in 519ms
Done in 2.15s.
把构建产物部署到 nginx 根目录:
# rm -rf /var/www/html/*
# cp -r /opt/web-build/dist/* /var/www/html/
# ls /var/www/html/
assets favicon.ico index.html
六、初始化存储目录
存储根目录默认约定为 /var/docat(可通过环境变量 DOCAT_STORAGE_PATH 调整,见 C 篇),API 进程以 www-data 身份运行,因此属主要提前设定:
# mkdir -p /var/docat
# chown -R www-data:www-data /var/docat
API 启动后会自动创建 doc/ 子目录(文档)与 db.json(元数据),无需手工建。
七、systemd 服务化 API 进程
创建单元文件 /etc/systemd/system/docat-api.service(全文如下,可直接照抄):
[Unit]
Description=docat API server (FastAPI/uvicorn)
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/docat-src
Environment=DOCAT_STORAGE_PATH=/var/docat
ExecStart=/opt/docat-venv/bin/python -m uvicorn --host 127.0.0.1 --port 5000 docat.app:app
Restart=on-failure
RestartSec=3
[Install]
WantedBy=multi-user.target
要点说明:
--host 127.0.0.1:API 只监听本机回环,外部流量一律经 nginx,避免后端直接暴露;DOCAT_STORAGE_PATH=/var/docat:显式声明存储根,与 nginx 的/doc静态目录指向一致;WorkingDirectory指向源码目录即可,应用通过 site-packages 导入,不依赖运行目录内的文件。
启用并启动:
# systemctl daemon-reload
# systemctl enable --now docat-api.service
Created symlink /etc/systemd/system/multi-user.target.wants/docat-api.service → /etc/systemd/system/docat-api.service.
# systemctl status docat-api --no-pager -n 3
实测回显:
● docat-api.service - docat API server (FastAPI/uvicorn)
Loaded: loaded (/etc/systemd/system/docat-api.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2026-10-28 05:12:34 UTC; 11min ago
Main PID: 1076 (python)
Tasks: 6 (limit: 2932)
Memory: 42.0M
CPU: 1.526s
CGroup: /system.slice/docat-api.service
└─1076 /opt/docat-venv/bin/python -m uvicorn --host 127.0.0.1 --port 5000 docat.app:app
Oct 28 05:23:43 docat-lab python[1076]: INFO: 127.0.0.1:38806 - "POST /api/getting-started/1.1.0 HTTP/1.0" 201 Created
Oct 28 05:23:43 docat-lab python[1076]: INFO: 127.0.0.1:38814 - "PUT /api/getting-started/1.1.0/tags/latest HTTP/1.0" 201 Created
Oct 28 05:23:43 docat-lab python[1076]: INFO: 127.0.0.1:38820 - "GET /api/projects/getting-started HTTP/1.0" 200 OK
API 进程常驻内存约 42 MB(上传若干文档后),资源占用非常轻。此时先做一次后端自检:
# curl -s http://127.0.0.1:5000/api/stats
{"n_projects":0,"n_versions":0,"storage":"0 bytes"}
八、nginx 站点配置
写入 /etc/nginx/sites-available/docat(内容基于官方模板 docat/nginx/default,把监听端口改为 8143,上传上限写为 100M):
upstream python_backend {
server 127.0.0.1:5000;
}
server {
listen 8143 default_server;
listen [::]:8143 default_server;
root /var/www/html;
add_header Content-Security-Policy "frame-ancestors 'self';";
index index.html index.htm index.pdf /index.html;
server_name _;
location /doc {
root /var/docat;
absolute_redirect off;
}
location /api {
client_max_body_size 100M;
proxy_pass http://python_backend;
}
location / {
try_files $uri $uri/ /index.html =404;
}
}
启用站点并启动 nginx(Debian/Ubuntu 系统自带默认站点需要移除,否则 8143 之外的默认监听会与之冲突):
# rm -f /etc/nginx/sites-enabled/default
# ln -sf /etc/nginx/sites-available/docat /etc/nginx/sites-enabled/docat
# nginx -t
nginx: the configuration file /etc/nginx/sites-enabled/docat syntax is ok
nginx: configuration file /etc/nginx/sites-enabled/docat test is successful
# systemctl restart nginx
验证端口监听:
# ss -ltn | grep -E '8143|5000'
LISTEN 0 2048 127.0.0.1:5000 0.0.0.0:*
LISTEN 0 511 0.0.0.0:8143 0.0.0.0:*
LISTEN 0 511 [::]:8143 [::]:*
排障实录 1:改完 nginx 配置后 /api 一直 404
现象:首页 200 正常,但 curl http://127.0.0.1:8143/api/stats 返回 nginx 的 HTML 404 页面,而不是后端 JSON。
定位过程:先排除后端问题——直连 uvicorn 正常:
# curl -s http://127.0.0.1:5000/api/stats
{"n_projects":0,"n_versions":0,"storage":"0 bytes"}
再核对磁盘上的站点配置与生效配置(nginx -T),两者完全一致、location /api 存在,说明不是配置文件写错。真正原因:apt 安装 nginx 时服务已自动启动(加载的是安装时的默认配置),随后用 systemctl enable --now nginx 启用时,服务已在运行、配置不会重新加载——enable --now 对已运行的服务不执行 restart/reload。
解决:
# systemctl restart nginx
重启后 /api 立即恢复正常。经验法则:修改站点配置后必须 restart 或 reload,enable --now 只保证"启动",不等于"重载"。
九、上传文档验证(全链路)
用 MkDocs 构建一份真实文档做端到端验证(MkDocs 只是文档生成器示例,任何能产出 index.html 的静态文档都可以):
# /opt/docat-venv/bin/pip install mkdocs
# mkdir -p /opt/demo-docs/docs
# cat > /opt/demo-docs/mkdocs.yml <<'EOF'
site_name: getting-started
theme: mkdocs
EOF
# cat > /opt/demo-docs/docs/index.md <<'EOF'
# Getting Started
Welcome to the demo documentation.
## Usage
This page is hosted by docat.
EOF
# cd /opt/demo-docs && /opt/docat-venv/bin/mkdocs build -d /tmp/site-v2
INFO - Documentation built in 0.03 seconds
# cd /tmp/site-v2 && zip -qr /tmp/getting-started-1.0.0.zip .
# ls -la /tmp/getting-started-1.0.0.zip
-rw-r--r-- 1 root root 856495 Oct 28 05:23 /tmp/getting-started-1.0.0.zip
9.1 上传两个版本并打 latest 标签
# curl -s -X POST -F 'file=@/tmp/getting-started-1.0.0.zip' http://127.0.0.1:8143/api/getting-started/1.0.0
{"message":"Documentation uploaded successfully"}
# curl -s -X POST -F 'file=@/tmp/getting-started-1.0.0.zip' http://127.0.0.1:8143/api/getting-started/1.1.0
{"message":"Documentation uploaded successfully"}
# curl -s -X PUT http://127.0.0.1:8143/api/getting-started/1.1.0/tags/latest
{"message":"Tag latest -> 1.1.0 successfully created"}
9.2 查询项目详情
# curl -s http://127.0.0.1:8143/api/projects/getting-started
{"name":"getting-started","storage":"3 MB","versions":[{"name":"1.1.0","timestamp":"2026-10-28T05:23:43.595218","tags":["latest"],"hidden":false},{"name":"1.0.0","timestamp":"2026-10-28T05:23:43.578687","tags":[],"hidden":false}]}
9.3 浏览器访问验证
- 首页(项目列表):
http://<服务器IP>:8143/→ 实测返回 HTTP 200; - 文档页:
http://<服务器IP>:8143/doc/getting-started/latest/→ 实测返回 HTTP 200:
# curl -s -o /dev/null -w 'GET /doc/getting-started/latest/ => %{http_code}\n' http://127.0.0.1:8143/doc/getting-started/latest/
GET /doc/getting-started/latest/ => 200
9.4 磁盘布局(理解存储模型)
# ls -la /var/docat/doc/getting-started/
total 16
drwxr-xr-x 4 www-data www-data 4096 Oct 28 05:23 .
drwxr-xr-x 3 www-data www-data 4096 Oct 28 05:23 ..
drwxr-xr-x 8 www-data www-data 4096 Oct 28 05:23 1.0.0
drwxr-xr-x 8 www-data www-data 4096 Oct 28 05:23 1.1.0
lrwxrwxrwx 1 www-data www-data 5 Oct 28 05:23 latest -> 1.1.0
每个版本是一个真实目录,latest 标签是指向版本目录的符号链接——这就是"标签切换零成本"的底层实现,也是备份时必须保留符号链接属性的原因(tar 打包时注意不要加 --dereference)。
十、k8s / Helm 部署路径说明(未实测)
截至 2026-10-28 查询官方仓库 1.6.1 标签:DOCAT 官方未提供 Kubernetes manifests 或 Helm Chart,官方发行物只有源码仓库与预构建应用包(ghcr.io 上的官方成品包)两种形态,均无配套的编排描述文件。社区如有 k8s 需求,需自行编写 Deployment/Service/PVC 描述(存储根 /var/docat 与 nginx 静态目录需要持久卷),本专栏未对该路径做实测,此节仅作事实说明以免误导选型。
十一、排障实录汇总
| # | 现象 | 根因 | 解决 |
|---|---|---|---|
| 1 | yarn build 报 Could not resolve './../assets/getting-started.md' in src/pages/Help.tsx | 源码中 web/src/assets/getting-started.md 是指向仓库 doc/getting-started.md 的符号链接,把 web 目录单独拷出后链接目标丢失(悬空链接) | 删除悬空链接后,把真实文件拷入:cp /opt/docat-src/doc/getting-started.md /opt/web-build/src/assets/,重新 yarn build |
| 2 | pip install /opt/docat-src/docat 报 could not create 'docat.egg-info': Read-only file system | pip 构建时要在源码目录写 egg-info,源码目录为只读挂载时构建失败 | 把源码拷贝到可写路径再安装:cp -r /opt/docat-src/docat /opt/docat-build && pip install /opt/docat-build |
| 3 | 首页 200 但 /api/* 全部 404(nginx HTML 404 页) | nginx 随 apt 安装已自启,之后 systemctl enable --now nginx 不会重载新站点配置 | systemctl restart nginx 后恢复;见第八节排障实录 1 |
| 4 | 上传 zip 后返回 Documentation uploaded successfully, but no index.html found at root of archive. | 打包时把外层目录打进去了(zip 根是 site/ 而不是 index.html),服务端解包后找不到入口 | 在站点目录内打包(cd site && zip -r ../x.zip .),保证 index.html 位于 zip 根 |
十二、部署检查清单
-
python3 -c 'from docat.app import app'无报错 -
systemctl is-active docat-api返回 active,/opt/docat-venv/bin/python -m uvicorn ...进程常驻(内存 ~42 MB) -
ss -ltn可见 8143(对外)与 127.0.0.1:5000(对内) -
curl http://127.0.0.1:8143/api/stats返回 JSON 统计 - 首页
/与文档页/doc/<项目>/<版本>/均 200 -
/var/docat属主为 www-data,版本目录与 latest 符号链接结构正确
完成部署后,建议继续阅读 《DOCAT 配置参数详解》 了解环境变量、反代与认证的逐项调优,以及 《DOCAT 常用 CLI 命令详解》 掌握日常发布操作。