DOCAT 常用 CLI 命令详解(docatl 与 HTTP API 实战)

docatl v1.1.1 与 curl 双路径实测 DOCAT 1.6.1 全部操作:push/tag/claim/hide/show/push-icon/rename/delete 逐条真机回显,含 CI 集成范式、备份恢复闭环演练(db.json 丢失到令牌复效)与 3 个排障实录。

DOCAT文档托管Ubuntu22.042026/10/28

DOCAT 常用 CLI 命令详解(docatl 与 HTTP API 实战)

DOCAT 的日常运维(上传文档、打标签、认领项目、删除版本、备份恢复)通过两条等价路径完成:官方命令行工具 docatl(Go 编写的独立二进制,仓库 docat-org/docatl,当前版本 v1.1.1,查询日期 2026-10-28)与原生 HTTP API(curl 即可调用)。本文基于 Ubuntu 22.04 + DOCAT 1.6.1 实测环境(Web 端口 8143,部署见 《DOCAT Ubuntu 22.04 安装部署指南》),对每条命令给出 docatl 与 curl 双写法及真机回显。

前置阅读:《DOCAT 介绍与选型指南》(组件定位)、《DOCAT 配置参数详解》(认证机制与错误码)。

一、安装 docatl

官方在 GitHub Releases 提供各平台静态二进制(v1.1.1 资产列表:docatl_1.1.1_linux_amd64 等)。Linux amd64 服务器上的安装:

# curl -sL -o /usr/local/bin/docatl https://github.com/docat-org/docatl/releases/download/v1.1.1/docatl_1.1.1_linux_amd64
# chmod +x /usr/local/bin/docatl
# docatl --help
Error: unknown flag: --version
Usage:
  docatl [command]

Available Commands:
  build       Build a documentation artifact to push to a docat server
  claim       Claim a docat project
  completion  Generate the autocompletion script for the specified shell
  delete      Delete documentation from a docat server
  help        Help about any command
  hide        Hide a project version.
  push        Push documentation to a docat server
  push-icon   Push an icon for a project
  rename      Rename a project
  show        Show a hidden project version.
  tag         Tag an existing documentation on a docat server

Flags:
      --api-key string   docat Api Key
      --config string    config file (default "/.docatl.yaml")
  -h, --help             help for docatl
      --host string      docat hostname (e.g. https://docat.company.com:8000)

Use "docatl [command] --help" for more information about a command.

注意:v1.1.1 没有 --version 旗标也没有 version 子命令(上面的回显即尝试 docatl --version 的真实输出),确认版本请对照下载的 release 文件名。

全局参数三个:--host(服务地址)、--api-key(认领令牌)、--config(配置文件,默认 ~/.docatl.yaml,可把 host/api-key 写进去省略每次输入)。非 80 端口的服务必须在 --host 里显式写端口(本文服务在 8143,故命令均为 --host http://127.0.0.1:8143),漏写端口时 docatl 会按默认 80 连接并报 connection refused(见第九节排障实录 2)。

二、核心工作流总览

一个文档项目从发布到下线的完整生命周期命令链:

1. 准备静态文档产物(MkDocs/Sphinx 构建,index.html 必须在 zip 根)
2. docatl push  → 上传版本(可同时 --tag latest)
3. docatl tag   → 追加/调整标签(latest/stable 等)
4. docatl claim → 认领项目换取令牌(每个项目仅一次)
5. docatl push-icon / rename / hide / show → 装饰与治理(需令牌)
6. docatl delete → 下线版本(需令牌)
7. 备份:tar 打包存储根(含 db.json)

准备测试文档

用 MkDocs 构建一份文档作为测试素材(任何含 index.html 的静态目录均可):

# /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

三、push —— 上传文档版本

上传 zip 到指定项目与版本。首次上传会自动创建项目。

docatl 写法(含一步式打 latest 标签):

# docatl push /tmp/getting-started-1.0.0.zip cli-project 1.0.0 --host http://127.0.0.1:8143 --tag latest
2026/10/28 05:28:32 Successfully pushed documentation version 1.0.0 to project cli-project
2026/10/28 05:28:32 Successfully tagged version 1.0.0 of project cli-project as latest

curl 等价写法(POST 表单,字段名 file):

# curl -s -X POST -F 'file=@/tmp/getting-started-1.0.0.zip' http://127.0.0.1:8143/api/cli-project/1.0.0
{"message":"Documentation uploaded successfully"}

验证上传结果:

# curl -s http://127.0.0.1:8143/api/projects/cli-project
{"name":"cli-project","storage":"1 MB","versions":[{"name":"1.0.0","timestamp":"2026-10-28T05:28:32.223520","tags":["latest"],"hidden":false}]}

语义要点(均实测验证):

  • 上传到不存在的版本号=创建,无需令牌;上传到已存在的版本号=覆盖,需令牌(401/201 对照实测见 C 篇 4.1);
  • zip 根必须有 index.html,否则返回成功但附提示:Documentation uploaded successfully, but no index.html found at root of archive.;
  • 项目名不能使用保留字 api/doc/upload/claim/delete/help(400,实测见 C 篇错误码表)。

四、tag —— 版本打标签

标签是指向版本的符号链接(服务端实现),常用于 latest、stable。

docatl 写法:

# docatl tag getting-started 1.1.0 latest --host http://127.0.0.1:8143
2026/10/28 05:16:45 Successfully tagged version 1.1.0 of project getting-started as latest

curl 等价写法(PUT 方法):

# 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"}

标签重复执行是安全的切换操作(符号链接重指向),实测连续 tag 到不同版本即"版本回退":

# 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

约束:标签不能覆盖"真实版本目录"(409 Tag <标签> would overwrite an existing version!);真实版本也不能覆盖已有标签(409 Cannot overwrite existing tag with new version.)。

五、claim —— 认领项目换取令牌

docatl 写法:

# docatl claim cli-project --host http://127.0.0.1:8143
2026/10/28 05:28:47 Successfully claimed project cli-project. Store and use the following token: f406543d74dd520ad4ce4535cb5910ca

curl 等价写法(注意:1.6.1 实际是 GET 请求,官方 getting-started 文档同此写法):

# curl -s http://127.0.0.1:8143/api/demo-project/claim
{"message":"Project demo-project successfully claimed","token":"7aede69addc833b337103e1fc48ec1c8"}

关键语义(实测):

  • 每个项目只能认领一次,重复认领返回 409:{"message":"Project demo-project is already claimed!"};
  • 令牌请立即妥善保存,服务端只存哈希(PBKDF2-HMAC-SHA256/10 万轮,见 db.json),遗失无法找回;
  • 需要令牌的操作:覆盖上传、delete、rename、hide、show、替换已有图标;
  • 不需要令牌的操作:首次上传新版本、首次设置图标、tag、一切读操作。

六、hide / show —— 版本隐藏与恢复

隐藏的版本不出现在版本下拉与搜索结果中,但直链仍可访问(便于"软下线")。

# docatl hide getting-started 1.0.0 --host http://127.0.0.1:8143 --api-key 7aede69addc833b337103e1fc48ec1c8
2026/10/28 05:16:57 Successfully hid version 1.0.0 of project getting-started
# 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}]}

隐藏后 1.0.0 从列表消失;带 include_hidden=true 参数可见全量:

# curl -s 'http://127.0.0.1:8143/api/projects?include_hidden=true'
{"projects":[{"name":"getting-started","logo":false,"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":true}]}]}

恢复显示(curl 写法):

# curl -s -X POST -H 'Docat-Api-Key: 7aede69addc833b337103e1fc48ec1c8' http://127.0.0.1:8143/api/getting-started/1.0.0/show
{"message":"Version 1.0.0 is now shown"}

七、push-icon / rename —— 图标与重命名

上传项目图标(首次无需令牌,替换需令牌;文件必须是图片类型,服务端用 libmagic 识别):

# docatl push-icon getting-started /tmp/logo.png --host http://127.0.0.1:8143 --api-key 7aede69addc833b337103e1fc48ec1c8
2026/10/28 05:16:57 Successfully pushed icon /tmp/logo.png for project getting-started

curl 等价:curl -X POST -F 'file=@logo.png' -H 'Docat-Api-Key: <token>' http://127.0.0.1:8143/api/<项目>/icon。图标落盘在项目根(/var/docat/doc/<项目>/logo)。

重命名项目(需令牌):

# docatl rename getting-started getting-started-v2 --host http://127.0.0.1:8143 --api-key 7aede69addc833b337103e1fc48ec1c8
2026/10/28 05:16:57 Successfully renamed project getting-started to getting-started-v2

curl 等价:curl -X PUT -H 'Docat-Api-Key: <token>' http://127.0.0.1:8143/api/<旧名>/rename/<新名>。重命名同时更新磁盘目录与认领记录(令牌保持有效)。

八、delete —— 删除版本(含重要坑位)

成功路径实测(无图标项目):

# docatl delete cli-project 1.0.0 --host http://127.0.0.1:8143 --api-key f406543d74dd520ad4ce4535cb5910ca
2026/10/28 05:28:47 Successfully deleted version 1.0.0 of project cli-project
# curl -s http://127.0.0.1:8143/api/projects/cli-project
{"message":"Project cli-project does not exist"}

删除最后一个版本后项目自动从列表消失。删除 latest 标签指向的版本时,死链标签会被服务端一并清理。

排障实录 1:delete 报 500 Internal Server Error(1.6.1 上游缺陷)

现象:删除设置了项目图标的项目的最后一个版本时,返回 500:

# docatl delete docatl-renamed 2.0.0 --host http://127.0.0.1:8143 --api-key 90f45f11c6f42e2387894d1831845436
2026/10/28 05:16:57 unable to delete documentation: (status code: 500) Internal Server Error

定位(journalctl -u docat-api 实录 traceback 末段):

Oct 28 05:16:57 docat-lab python[1076]:   File "/opt/docat-src/docat/utils.py", line 102, in remove_docs
Oct 28 05:16:57 docat-lab python[1076]:     docs.parent.rmdir()
Oct 28 05:16:57 docat-lab python[1076]: OSError: [Errno 39] Directory not empty: '/var/docat/doc/docatl-renamed'

根因:服务端删除版本后会尝试清空整个项目目录(rmdir),但"目录是否为空"的判断只检查子目录,项目图标(logo 文件)不在检查范围内——logo 文件残留导致 rmdir 失败抛 500。注意此时版本数据本身已删除成功,500 只发生在收尾清理阶段;该缺陷在 v1.6.1 存在,属上游代码问题。

规避与恢复:

# rm -f /var/docat/doc/<项目>/logo && rmdir /var/docat/doc/<项目> && echo cleaned
cleaned

最佳实践:删除整个项目前先规划图标;或接受"删最后版本会 500 + 手工清理目录"的运维口径,升级版本时关注官方对该缺陷的修复。

九、CI 流水线集成与备份恢复

9.1 CI 集成范式

DOCAT 官方 README 给出的 CI 场景一行命令(配 docatl):

# docatl push --host http://docat.internal:8143 ./docs myproject 1.2.3 --tag latest

(docatl build 可先把文档目录打包成 zip:docatl build ./site → 生成 site.zip 并提示 Push documentation with: docatl push site.zip,实测产物 850988 字节。)

纯 curl 的 CI 范式(不装 docatl 时的选择):

# curl -X POST -F "file=@docs.zip" http://docat.internal:8143/myproject/1.2.3

官方 README 该示例未带 /api 前缀是旧版接口写法;1.6.1 实测必须带 /api(本文第三节 curl 实测为证)。

9.2 备份:打包存储根

需要备份的全部状态就是 DOCAT_STORAGE_PATH 指向的目录(文档 + 认领令牌库):

# tar -czf /opt/backup/docat-full-backup.tar.gz -C /var docat
# ls -la /opt/backup/docat-full-backup.tar.gz
-rw-r--r-- 1 root root 857153 Oct 28 05:20 /opt/backup/docat-full-backup.tar.gz
# tar -tzf /opt/backup/docat-full-backup.tar.gz | head -4
docat/
docat/doc/
docat/doc/demo-renamed/
docat/doc/demo-renamed/logo

注意 tar 不要加 --dereference(会破坏 latest 等标签符号链接);cron 化建议每日凌晨全量(该目录与文档总量同量级,实测本项目 zip 包 856 KB 即备份包 857 KB)。

9.3 恢复演练:db.json 丢失 → 令牌失效 → 恢复 → 令牌复效

db.json 是令牌唯一载体,用它验证备份的完整闭环(无图标项目 restore-demo,token=c1cf37f13ff730d3f2735f492b43a28a):

第一步:正常状态下令牌有效(401 对照):

# curl -s -X DELETE http://127.0.0.1:8143/api/restore-demo/1.0.0
{"message":"Please provide a header with a valid Docat-Api-Key token for restore-demo"}

第二步:模拟 db.json 丢失,令牌校验失效:

# rm -f /var/docat/db.json
# curl -s -w ' HTTP %{http_code}\n' -X DELETE -H 'Docat-Api-Key: c1cf37f13ff730d3f2735f492b43a28a' http://127.0.0.1:8143/api/restore-demo/1.0.0
{"message":"Please provide a header with a valid Docat-Api-Key token for restore-demo"} HTTP 401

第三步:从备份恢复 db.json,令牌立即复效:

# tar -xzf /opt/backup/docat-full-backup.tar.gz -C /restore-extract
# cp /restore-extract/docat/db.json /var/docat/db.json && chown www-data:www-data /var/docat/db.json
# curl -s -w ' HTTP %{http_code}\n' -X DELETE -H 'Docat-Api-Key: c1cf37f13ff730d3f2735f492b43a28a' http://127.0.0.1:8143/api/restore-demo/1.0.0
{"message":"Successfully deleted version '1.0.0'"} HTTP 200

结论:文档数据与令牌库同目录同生命周期,全量备份即完整可恢复点;恢复后无需重启服务(令牌校验每次请求实时读库)。

排障实录 2:docatl 报 connection refused 但服务正常

现象:docatl push ... --host http://127.0.0.1(漏写端口)报:

unable to upload documentation: Post "http://127.0.0.1/api/cli-project/1.0.0": dial tcp 127.0.0.1:80: connect: connection refused

根因:docatl 对 --host 不做端口补全,非 80/443 部署必须显式写端口;本环境 Web 层监听 8143。解决:--host http://127.0.0.1:8143。

排障实录 3:官方文档 API 路径与 1.6.1 行为差异点

  • 上传路由实测为 POST /api/<项目>/<版本>(无尾斜杠);带尾斜杠的请求由框架自动 307 重定向,个别客户端不发重定向后续请求时表现为"上传无响应",建议一律不带尾斜杠;
  • claim 为 GET 请求(见第五节);旧教程中 POST /claim 写法在 1.6.1 会 405;
  • curl 上传务必用 -F file=@xxx.zip 表单字段名 file,用 --data-binary 直发 body 会因缺 multipart 字段而 422。

十、命令速查表

操作docatlcurl 等价令牌
上传/覆盖版本docatl push <zip> <项目> <版本> [--tag <标签>]POST /api/<项目>/<版本>(form: file)覆盖需
打标签docatl tag <项目> <版本> <标签>PUT /api/<项目>/<版本>/tags/<标签>否
认领docatl claim <项目>GET /api/<项目>/claim-
隐藏/恢复docatl hide/show <项目> <版本>POST /api/<项目>/<版本>/hide 或 /show需
图标docatl push-icon <项目> <png>POST /api/<项目>/icon(form: file)替换需
重命名docatl rename <旧> <新>PUT /api/<项目>/rename/<新名>需
删除版本docatl delete <项目> <版本>DELETE /api/<项目>/<版本>需
项目列表(Web 界面)GET /api/projects[?include_hidden=true]否
系统统计(Web 界面)GET /api/stats否
API 文档-GET /api/docs(Swagger)/ GET /api/v1/openapi.json否