ManageMeals 1.9.3 常用 CLI 命令与工具详解
ManageMeals api v1.9.3 自托管命令行工具箱实测:docker compose 栈运维全回显(down/up/pull/restart)、mongosh/mongodump/mongorestore 备份恢复踩坑(--archive 容器路径陷阱)、valkey-cli 探活、Typesense 28.0 multi_search 直查、API curl 登录/续期/导入三态 400/标签 E11000、scraper 独立调试(实测日期 2026-11-02)
ManageMeals 1.9.3 常用 CLI 命令与工具详解
目标:给出 ManageMeals(manage-meals-api v1.9.3 / manage-meals-web v1.7.3)自托管日常运维的完整命令行工具箱——
docker compose栈运维、mongosh/mongodump/mongorestore数据库三件套、valkey-cli缓存探活、Typesense 与业务 API 的curl直查、scraper 独立调试,全部命令与回显来自实测环境(Ubuntu 24.04.5 LTS / x86_64 / Docker 29.9.2 / Docker Compose v5.6.1,实测日期 2026-11-02)。栈的部署过程见站内 《ManageMeals Docker Compose 部署指南》,环境变量含义见 《ManageMeals 1.9.3 配置参数详解》,组件选型见 《ManageMeals 介绍与选型指南》。说明:ManageMeals 官方没有提供独立 CLI 管理工具(无
managemeals命令),日常「命令行运维」实际由「compose 运维 + 容器自带数据库工具 + HTTP 接口 curl」三类组成,本文按此展开。本文验证天然不依赖浏览器,全部为终端实测回显。
一、环境信息
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 24.04.5 LTS(x86_64) |
| Docker / Compose | 29.9.2 / v5.6.1(docker compose 子命令形态) |
| Compose 项目 | manage-meals-v1.9.3-stack,网络 manage-meals-net(10.89.63.0/24) |
| 对外端口 | web 8146、api 8148、typesense 8151、scraper 8153、mongo-express 8081 |
| 演示账号 | admin@example.com / q1w2e3r4(uuid d575f1c9-2142-4451-ad8a-c4f09f285ca5) |
| 数据库凭据 | MongoDB root / q1w2e3r4;Typesense API key q1w2e3r4 |
| 容器自带工具 | mongo 镜像内含 mongosh、mongodump、mongorestore;valkey 镜像内含 valkey-cli |
| 宿主工具 | curl、python3(解析 JSON/解码 JWT,可换 jq) |
| 持久化 | bind mount ./data/mongo、./data/typesense——down/up 不丢数据 |
二、工具概览
ManageMeals 命令行运维工具箱全貌,按使用频率排序:
| 工具 | 所在位置 | 用途 | 本文小节 |
|---|---|---|---|
docker compose | 宿主 | 栈生命周期、日志、进入容器 | 4.1 |
mongosh | mongo 容器内 | 查集合/索引/文档、排障兜底 | 4.2 |
mongodump / mongorestore | mongo 容器内 | 逻辑备份与恢复演练 | 4.3 |
valkey-cli | valkey 容器内 | 缓存连通性探活 | 4.4 |
| Typesense HTTP | curl(宿主或容器内) | 搜索索引健康与直查 | 4.5 |
| ManageMeals API | curl | 注册/登录/导入/搜索/业务资源 | 4.6 |
| scraper HTTP | curl | URL 解析独立调试 | 4.7 |
💡 提示:mongo-express 是唯一的 Web 管理界面(非 CLI),生产建议移除或开启 BasicAuth,理由见配置参数详解 6.3 必改清单。
三、前置条件
3.1 栈在运行
cd /opt/manage-meals && docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
manage-meals-v193-stack-manage-meals-api-1 ghcr.io/managemeals/manage-meals-api:latest "docker-entrypoint.s…" manage-meals-api 10 seconds ago Up 8 seconds 0.0.0.0:8148->3000/tcp, [::]:8148->3000/tcp
manage-meals-v193-stack-manage-meals-web-1 ghcr.io/managemeals/manage-meals-web:latest "docker-entrypoint.s…" manage-meals-web 10 seconds ago Up 8 seconds 0.0.0.0:8146->3000/tcp, [::]:8146->3000/tcp
manage-meals-v193-stack-mongo-1 mongo:7 "docker-entrypoint.s…" mongo 10 seconds ago Up 9 seconds 27017/tcp
manage-meals-v193-stack-mongo-express-1 mongo-express "/sbin/tini -- /dock…" mongo-express 10 seconds ago Up 8 seconds 0.0.0.0:8081->8081/tcp, [::]:8081->8081/tcp
manage-meals-v193-stack-recipe-scraper-1 ghcr.io/managemeals/manage-meals-scraper:latest "gunicorn -w 1 -b 0.…" recipe-scraper 10 seconds ago Up 8 seconds 0.0.0.0:8153->8000/tcp, [::]:8153->8000/tcp
manage-meals-v193-stack-search-sync-1 ghcr.io/managemeals/manage-meals-search-sync:latest "docker-entrypoint.s…" search-sync 10 seconds ago Up 8 seconds
manage-meals-v193-stack-typesense-1 typesense/typesense:28.0 "/opt/typesense-serv…" typesense 10 seconds ago Up 8 seconds 0.0.0.0:8151->8108/tcp, [::]:8151->8108/tcp
manage-meals-v193-stack-valkey-1 valkey/valkey:8 "tini -- docker-entr…" valkey 10 seconds ago Up 9 seconds 6379/tcp
(COMMAND 列的 … 是 Docker 自身对长命令的截断显示,非本文省略。)
3.2 宿主验证工具
curl --version | head -1 && python3 --version
本文所有 API/Typesense 验证只用 curl + python3(JSON 解析与 JWT 解码),无其他依赖。
3.3 凭据就位
后续所有命令直接内联本文凭据(q1w2e3r4 等,见第一章表)。生产环境不要把密码写进命令行历史,见「五、注意事项」第 2 条。
四、各工具详解
4.1 docker compose:栈运维主力
4.1.1 状态查看三件套
docker compose ps # 服务状态
docker compose logs --tail 5 manage-meals-web # 单服务日志
docker compose config --quiet && echo 'config ok (exit 0)' # 语法校验
manage-meals-web-1 | Listening on http://0.0.0.0:3000
config ok (exit 0)
config --quiet 无输出且 exit 0 即 compose 文件合法,改配置后先跑它再 up。
4.1.2 停止与启动(数据不丢)
docker compose down
Container manage-meals-v193-stack-mongo-express-1 Stopping
Container manage-meals-v193-stack-manage-meals-web-1 Stopping
Container manage-meals-v193-stack-manage-meals-web-1 Stopped
Container manage-meals-v193-stack-manage-meals-web-1 Removing
Container manage-meals-v193-stack-mongo-express-1 Stopped
Container manage-meals-v193-stack-mongo-express-1 Removing
Container manage-meals-v193-stack-manage-meals-web-1 Removed
Container manage-meals-v193-stack-manage-meals-api-1 Stopping
Container manage-meals-v193-stack-mongo-express-1 Removed
Container manage-meals-v193-stack-manage-meals-api-1 Stopped
Container manage-meals-v193-stack-manage-meals-api-1 Removing
Container manage-meals-v193-stack-manage-meals-api-1 Removed
Container manage-meals-v193-stack-recipe-scraper-1 Stopping
Container manage-meals-v193-stack-search-sync-1 Stopping
Container manage-meals-v193-stack-valkey-1 Stopping
Container manage-meals-v193-stack-valkey-1 Stopped
Container manage-meals-v193-stack-valkey-1 Removing
Container manage-meals-v193-stack-valkey-1 Removed
Container manage-meals-v193-stack-recipe-scraper-1 Stopped
Container manage-meals-v193-stack-recipe-scraper-1 Removing
Container manage-meals-v193-stack-recipe-scraper-1 Removed
Container manage-meals-v193-stack-search-sync-1 Stopped
Container manage-meals-v193-stack-search-sync-1 Removing
Container manage-meals-v193-stack-search-sync-1 Removed
Container manage-meals-v193-stack-mongo-1 Stopping
Container manage-meals-v193-stack-typesense-1 Stopping
Container manage-meals-v193-stack-mongo-1 Stopped
Container manage-meals-v193-stack-mongo-1 Removing
Container manage-meals-v193-stack-mongo-1 Removed
Container manage-meals-v193-stack-typesense-1 Stopped
Container manage-meals-v193-stack-typesense-1 Removing
Container manage-meals-v193-stack-typesense-1 Removed
Network manage-meals-net Removing
Network manage-meals-net Removed
docker compose up -d
Network manage-meals-net Creating
Network manage-meals-net Creating
Network manage-meals-net Created
Network manage-meals-net Created
Container manage-meals-v193-stack-valkey-1 Creating
Container manage-meals-v193-stack-recipe-scraper-1 Creating
Container manage-meals-v193-stack-mongo-1 Creating
Container manage-meals-v193-stack-typesense-1 Creating
Container manage-meals-v193-stack-valkey-1 Created
Container manage-meals-v193-stack-typesense-1 Created
Container manage-meals-v193-stack-mongo-1 Created
Container manage-meals-v193-stack-mongo-express-1 Creating
Container manage-meals-v193-stack-search-sync-1 Creating
Container manage-meals-v193-stack-recipe-scraper-1 Created
Container manage-meals-v193-stack-search-sync-1 Created
Container manage-meals-v193-stack-manage-meals-api-1 Creating
Container manage-meals-v193-stack-mongo-express-1 Created
Container manage-meals-v193-stack-manage-meals-api-1 Created
Container manage-meals-v193-stack-manage-meals-web-1 Creating
Container manage-meals-v193-stack-manage-meals-web-1 Created
Container manage-meals-v193-stack-valkey-1 Starting
Container manage-meals-v193-stack-mongo-1 Starting
Container manage-meals-v193-stack-recipe-scraper-1 Starting
Container manage-meals-v193-stack-typesense-1 Starting
Container manage-meals-v193-stack-valkey-1 Started
Container manage-meals-v193-stack-mongo-1 Started
Container manage-meals-v193-stack-mongo-express-1 Starting
Container manage-meals-v193-stack-recipe-scraper-1 Started
Container manage-meals-v193-stack-typesense-1 Started
Container manage-meals-v193-stack-search-sync-1 Starting
Container manage-meals-v193-stack-mongo-express-1 Started
Container manage-meals-v193-stack-search-sync-1 Started
Container manage-meals-v193-stack-manage-meals-api-1 Starting
Container manage-meals-v193-stack-manage-meals-api-1 Started
Container manage-meals-v193-stack-manage-meals-web-1 Starting
Container manage-meals-v193-stack-manage-meals-web-1 Started
down 默认删容器和网络、不动 bind mount 数据——实测重启后菜谱、用户、索引全部还在(4.2/4.5 回显可证)。加 -v 才会删卷(本栈用 bind mount,-v 也删不掉宿主目录,需手动清理)。
4.1.3 升级:官方口径 pull + up
docker compose pull
Image ghcr.io/managemeals/manage-meals-search-sync:latest Pulling
Image mongo:7 Pulling
Image mongo-express Pulled
Image valkey/valkey:8 Pulled
Image mongo:7 Pulled
Image typesense/typesense:28.0 Pulled
Image ghcr.io/managemeals/manage-meals-scraper:latest Pulled
Image ghcr.io/managemeals/manage-meals-api:latest Pulled
Image ghcr.io/managemeals/manage-meals-search-sync:latest Pulled
Image ghcr.io/managemeals/manage-meals-web:latest Pulled
随后 docker compose up -d 重建变化服务。注意官方 ghcr 只发 :latest(无版本 tag,按版本号拉取实测 not found),pull + up 即升级全部;要锁版本就改用 digest 引用,见部署指南 2.2。
4.1.4 单服务重启与进入容器
docker compose restart search-sync
Container manage-meals-v193-stack-search-sync-1 Restarting
Container manage-meals-v193-stack-search-sync-1 Started
进容器排障(脚本/管道场景务必加 -T,理由见 4.3 与注意事项):
docker compose exec -T mongo mongosh -u root -p q1w2e3r4 --authenticationDatabase admin
docker compose exec -T manage-meals-api printenv | sort # 验证注入参数
4.2 mongosh:数据库直查
mongosh 在 mongo 镜像内,宿主无需安装。查集合清单、索引与计数:
docker compose exec -T mongo mongosh -u root -p q1w2e3r4 --authenticationDatabase admin --quiet \
--eval 'let m=db.getSiblingDB("manage_meals"); printjson(m.getCollectionNames()); printjson(m.tags.getIndexes().map(i=>i.name)); print("recipes="+m.recipes.countDocuments({})+" users="+m.users.countDocuments({}))'
[
'tags',
'syncs',
'shoppinglists',
'mealplans',
'users',
'cookbooks',
'recipes'
]
[ '_id_', 'uuid_1', 'slug_1_createdByUuid_1' ]
recipes=1 users=1
要点:7 个集合由应用首启自建;tags 上的两个唯一索引(uuid_1、slug_1_createdByUuid_1)是 4.6.6 重复标签报错的根源;用户密码以 bcrypt 哈希存储(实测 password 字段前缀 $2b$10$),直查库不会泄露明文。排障时最有用的两条查询:m.users.findOne({email:"admin@example.com"}) 看账号状态字段(isAdmin/isBanned/subscriptionType),m.syncs.find() 看搜索同步水位。
4.3 mongodump / mongorestore:逻辑备份与恢复
备份(--archive 输出到 stdout 重定向成单文件,--gzip 压缩):
docker compose exec -T mongo mongodump \
--uri "mongodb://root:q1w2e3r4@localhost:27017/manage_meals" \
--authenticationDatabase admin --gzip --archive > mm-backup.tar.gz
mongodump version: 100.20.0
2026-11-01T19:09:05.751+0000 writing `manage_meals.tags` to `archive on stdout`
2026-11-01T19:09:05.751+0000 writing `manage_meals.syncs` to `archive on stdout`
...
2026-11-01T19:09:05.765+0000 done dumping `manage_meals.recipes` (1 document)
2026-11-01T19:09:05.767+0000 done dumping `manage_meals.cookbooks` (1 document)
7 集合各 1 document,产物 4411 字节。恢复演练务必先恢复到临时库再核对,不要直接盖生产库。这里有个实测踩坑:--archive=文件路径 的写法会失败——路径在容器内解析,宿主文件在容器里不存在:
docker compose exec -T mongo mongorestore ... --gzip --archive=/tmp/mm-bad.tar.gz
Failed: stat /tmp/mm-bad.tar.gz: no such file or directory
0 document(s) restored successfully. 0 document(s) failed to restore.
exit=1
正确形态是 stdin 管道(sh -c 包住命令,宿主文件重定向进容器):
docker compose exec -T mongo sh -c 'mongorestore --uri "mongodb://root:q1w2e3r4@localhost:27017" \
--authenticationDatabase admin --gzip --archive --nsFrom="manage_meals.*" --nsTo="mm_restore.*"' < mm-backup.tar.gz
2026-11-01T19:09:05.965+0000 reading metadata for `mm_restore.recipes` from `archive on stdin`
2026-11-01T19:09:06.090+0000 7 document(s) restored successfully. 0 document(s) failed to restore.
验证与清理:
docker compose exec -T mongo mongosh -u root -p q1w2e3r4 --authenticationDatabase admin --quiet \
--eval 'let m=db.getSiblingDB("mm_restore"); print("verify recipes="+m.recipes.countDocuments({})); printjson(m.dropDatabase())'
verify recipes=1
{ ok: 1, dropped: 'mm_restore' }
实测唯一索引(uuid_1、slug_1_createdByUuid_1)随备份文件一并还原,恢复后约束行为一致。定时备份用宿主 cron 包一条 docker compose exec -T mongo mongodump ... > /backup/$(date +%F).tar.gz 即可。
4.4 valkey-cli:缓存探活
docker compose exec -T valkey valkey-cli ping
PONG
valkey 未映射宿主端口,也可临时起一个同网络容器探测(实测验证完即删):
docker run --rm --network manage-meals-net valkey/valkey:8 valkey-cli -h valkey ping
PONG
API 只用 valkey 缓存鉴权结果(10 秒 TTL),此服务挂掉表现为 API 变慢而非报错,重启自动恢复。
4.5 Typesense HTTP:索引健康与直查
Typesense 无 CLI,运维全靠 HTTP(头名 X-TYPESENSE-API-KEY,值与 compose 里 TYPESENSE_API_KEY 一致):
curl -s http://localhost:8151/health
{"ok":true}
curl -s -H 'X-TYPESENSE-API-KEY: q1w2e3r4' http://localhost:8151/collections | python3 -c 'import sys,json;print([c["name"] for c in json.load(sys.stdin)])'
['recipes']
集合由 search-sync 首启自动创建(default_sorting_field: rating)。直查索引内容时注意一个版本坑:typesense 28.0 实测单集合搜索端点 GET /collections/recipes/search 已不可用:
{ "message": "Not Found"}
=404
要用多查询端点 POST /multi_search,且必须带 query_by(缺省报 400 "No search fields specified for the query."):
curl -s -X POST http://localhost:8151/multi_search -H 'X-TYPESENSE-API-KEY: q1w2e3r4' \
-d '{"searches":[{"collection":"recipes","q":"brownies","query_by":"title","per_page":3}]}' | head -c 200
{"results":[{"facet_counts":[],"found":1,"hits":[{"document":{"categories":[],"createdByUuid":"d575f1c9-2142-4451-ad8a-c4f09f285ca5","description":"A super easy brownie recipe for a squidgy chocolate bake...
用途:当应用内搜索无结果时,先 multi_search 直查索引,区分「索引没同步」与「应用查询逻辑」两层问题。
4.6 ManageMeals API curl:业务命令行入口
API 是唯一业务操作入口(Web 只是它的消费者)。以下按「登录 → 各资源」顺序给出实测命令。
4.6.1 登录与 JWT 解码
AT=$(curl -s -X POST http://localhost:8148/v1/auth/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@example.com","password":"q1w2e3r4"}' \
| python3 -c 'import sys,json;print(json.load(sys.stdin)["accessToken"])')
python3 -c "
import base64,json
p=json.loads(base64.urlsafe_b64decode('$AT'.split('.')[1]+'=='))
print('iat=%d exp=%d diff=%d'%(p['iat'],p['exp'],p['exp']-p['iat']))"
iat=1793559439 exp=1793560039 diff=600
diff=600 即 AUTH_ACCESS_TOKEN_EXPIRE_SEC 生效值;refreshToken 有效期约 30 天(2629746 秒)。
4.6.2 令牌续期:字段名坑
续期接口字段是 token 而不是直觉的 refreshToken,实测两种写法:
curl -s -X POST http://localhost:8148/v1/auth/refresh-token -H 'Content-Type: application/json' -d '{"refreshToken":"<RT>"}'
{"statusCode":400,"code":"FST_ERR_VALIDATION","error":"Bad Request","message":"body must have required property 'token'"}
curl -s -X POST http://localhost:8148/v1/auth/refresh-token -H 'Content-Type: application/json' -d '{"token":"<RT>"}' | head -c 120
{"accessToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiZDU3NWYxYzktMjE0Mi00NDUxLWFkOGEtYzRmMDlmMjg1Y2E1IiwiaWF...
4.6.3 列表与分页
curl -s "http://localhost:8148/v1/recipes" -H "Authorization: Bearer $AT" | python3 -m json.tool | head -6
{
"page": 1,
"total": 1,
"perPage": 20,
"data": [ ...
perPage 由 ITEMS_PER_PAGE 控制(默认 20),page/perPage 查询参数可翻页。
4.6.4 URL 导入:三种 400 与唯一正确姿势
导入接口的参数形态实测有三种组合,前两种都报错:
# 错误1:只传 JSON body
curl -s -X POST "http://localhost:8148/v1/recipes/import" -H "Authorization: Bearer $AT" \
-H 'Content-Type: application/json' -d '{"url":"https://www.bbcgoodfood.com/recipes/best-ever-chocolate-brownies-recipe"}'
{"statusCode":400,"code":"FST_ERR_VALIDATION","error":"Bad Request","message":"querystring must have required property 'url'"}
# 错误2:只传 query 不带 body
curl -s -X POST "http://localhost:8148/v1/recipes/import?url=https://www.bbcgoodfood.com/recipes/best-ever-chocolate-brownies-recipe" -H "Authorization: Bearer $AT"
{"statusCode":400,"code":"FST_ERR_VALIDATION","error":"Bad Request","message":"body must be object"}
# 正确:query 带 url + 空 JSON body
curl -s -X POST "http://localhost:8148/v1/recipes/import?url=https://www.bbcgoodfood.com/recipes/best-ever-chocolate-brownies-recipe" \
-H "Authorization: Bearer $AT" -H 'Content-Type: application/json' -d '{}'
{"slug":"best-ever-chocolate-brownies-recipe-4qzU1noI"}
http=200
两个实测要点:url 走 querystring、body 必须存在(空对象即可);同一 URL 重复导入生成新后缀副本而非覆盖(首次导入 slug 为 ...-1K978f4R,本次为 ...-4qzU1noI)。若导入返回 400 "We couldn't import a recipe from this URL...",先用 4.7 直连 scraper 判断是源站无结构化数据(实测 recipetineats.com 一个不存在的路径报 No Recipe Schema found)还是链路配置问题。
4.6.5 搜索
curl -s "http://localhost:8148/v1/search?q=brownies&c=recipes&p=1" -H "Authorization: Bearer $AT" \
| python3 -c 'import sys,json;d=json.load(sys.stdin);print("found=%s page=%s hits=%s"%(d["found"],d["page"],[h["document"]["title"] for h in d["hits"]]))'
found=1 page=1 hits=['Best ever chocolate brownies recipe']
q、c、p 三参数必填,c 当前仅支持 recipes,f 可附加 filter。注意新导入要等 search-sync 下一轮(固定 3 分钟 cron)才可搜到;实测栈重启后 search-sync 首跑会因 typesense 未就绪打出 503 重试栈(Server said: Not Ready or Lagging),随后自动恢复、无需干预(见 4.6.7 说明)。
4.6.6 标签与唯一索引
curl -s -X POST http://localhost:8148/v1/tags -H "Authorization: Bearer $AT" \
-H 'Content-Type: application/json' -d '{"name":"dessert"}'
{"statusCode":500,"error":"Internal Server Error","message":"Tag with slug already exists"}
http=500
API 日志同步打出 MongoDB 唯一索引冲突原文,可用来确认是索引层拦截:
{"level":50,...,"err":{"type":"MongoServerError","message":"E11000 duplicate key error collection: manage_meals.tags index: slug_1_createdByUuid_1 dup key: { slug: \"dessert\", createdByUuid: \"d575f1c9-...
4.6.7 其余业务端点速查
实测跑通且可用的命令族(详细请求体见部署指南 4.7 与取证结论):POST /v1/meal-plans(需 date + mealTypes 数组,元素为 {mealType, categoryUuids, tagUuids} 对象)、POST /v1/shopping-lists(返回 slug 如 weekend-baking-GYdtNgcXcg;加菜谱要用 PUT 传 recipeUuids,POST 时 recipeSlugs 不生效)、POST /v1/cookbooks(返回 slug 如 baking-bQrY)、GET /v1/tags|categories|cookbooks 等列表。鉴权语义两条实测:无请求头 401 Missing Authorization header,过期令牌 401 Invalid Authorization header。
4.7 scraper 直连调试
抓取器是独立 Flask 服务,可脱离 API 单测解析能力:
curl -s "http://localhost:8153?url=https://www.bbcgoodfood.com/recipes/best-ever-chocolate-brownies-recipe" | head -c 200
{"author":"Orlando Murrin","canonical_url":"https://www.bbcgoodfood.com/recipes/best-ever-chocolate-brownies-recipe","category":"Afternoon tea, Dessert, Treat","cook_time":35,"cuisine":"American","des...
(截断处为 description 字段开头。)返回结构化 JSON 即源站解析正常;报 No Recipe Schema found 说明该 URL 页面没有 schema.org 菜谱数据,换源站而非改配置。
五、注意事项
exec脚本场景务必-T:不带-T时 Docker 分配伪 TTY,管道取输出会混入回车符甚至阻塞;本文所有非交互命令均为exec -T实测形态。- 凭据不落历史:命令行内联密码会进
~/.bash_history与/proc进程列表。排障可内联,脚本化时改为docker compose exec读容器内环境变量,或用--eval文件。 - mongodump 非原子快照:备份期间写入会造成集合间时间点不一致,低峰执行;重要数据恢复前先在临时库演练(4.3 的
--nsTo手法)。 - 重复导入不覆盖:同 URL 每次导入生成新 slug 副本(4.6.4),批量迁移前先查重,多余副本在 Web 端删除。
- search-sync 启动 503 属预期竞态:compose 无 healthcheck 依赖顺序,typesense 就绪前 sync 首跑报 503 并自动重试,实测自愈;持续报错才需要查
TYPESENSE_API_KEY三处一致性。 - typesense 28.0 单集合搜索端点 404:直查一律用
POST /multi_search+query_by(4.5)。 - ghcr 仅
:latest:pull即取上游最新版,升级前用 digest 记录当前版本便于回滚(部署指南 2.2/10.2)。
六、常见问题
Q1:docker compose exec mongo mongosh ... | grep 卡住或输出错乱?
缺 -T,见 4.3/注意事项 1。
Q2:mongorestore --archive=/backup/backup.tar.gz 报 Failed: stat ...: no such file or directory?
路径在容器内解析。改用 exec -T mongo sh -c 'mongorestore ... --archive' < 宿主文件(4.3)。
Q3:导入接口怎么都 400?
看 message 定位:querystring must have required property 'url' = 没把 url 放 query;body must be object = 没带 JSON body。正确姿势 ?url= + -d '{}'(4.6.4)。
Q4:刚导入的菜谱 API 搜不到,typesense 直查也 404?
两件事叠加:等 search-sync 下一轮(3 分钟);直查用 /multi_search 而非单集合端点(4.5/4.6.5)。
Q5:/v1/* 全部 401?
区分 message:Missing Authorization header 是没带头;Invalid Authorization header 是令牌过期(默认 600 秒),用 refresh-token 接口续期,字段名 token(4.6.1/4.6.2)。
Q6:建标签 500 "Tag with slug already exists"?
唯一索引 slug_1_createdByUuid_1 拦截,属正常去重(4.6.6);换名或先 GET 列表确认。
Q7:注册接口 500 "User register is not enabled"?
USER_REGISTER_ENABLED 被关闭,见配置参数详解 5.2/FAQ Q3。
七、参考链接
- 站内:《ManageMeals Docker Compose 部署指南》、《ManageMeals 1.9.3 配置参数详解》、《ManageMeals 介绍与选型指南》
- 后端仓库:https://github.com/managemeals/manage-meals-api
- 前端仓库:https://github.com/managemeals/manage-meals-web
- 镜像发布处:https://ghcr.io/managemeals/
- MongoDB 备份工具官方文档:https://www.mongodb.com/docs/database-tools/mongodump/
- Typesense HTTP API 文档:https://typesense.org/docs/