记录日期:2026-10-19(多伦多)。本次排查针对 eooce-blog 的特定镜像,不是所有 Node.js / Vitest 问题的通用修复。
现象
直接在镜像内执行 npm test 时,出现 Node 原生断言和子进程通信错误:
RemoveEnvironmentCleanupHook
Assertion failed: (env) != nullptr
ERR_IPC_CHANNEL_CLOSED
这不能直接解释为“博客本身不能运行”。当时网站能读取文章,失败发生在测试运行器启动工作进程的阶段。
第一步:把测试与在线站点隔离
测试代码会清理测试数据,不能把正式数据库路径交给它。后续测试放在单独的临时 Docker 容器里,用独立的 /tmp/blog-api-test.db,不挂载主站数据目录。
第二步:减少并行变量
改用 Vitest 的 threads 池和一个工作线程后,原来的崩溃不再出现,但暴露了另一个错误:
TypeError: The "path" argument must be of type string. Received undefined
检查测试源码发现它依赖 BLOG_DB_PATH。项目源码有 vitest.config.ts 负责设置该变量,而发布镜像的 Dockerfile 没有复制这个配置文件。
因此,不能只更换线程池;还要明确给出隔离的测试数据库路径。
最终通过的命令
以下命令使用本次测试时固定的镜像摘要,不会自动追踪 latest:
docker run --rm --network none \
-e NODE_ENV=test \
-e BLOG_DB_PATH=/tmp/blog-api-test.db \
-e JWT_SECRET=isolated-test-only-secret \
ghcr.io/eooce/blog@sha256:abaccc2e7c241756548d2ef6d43633123fb28add6ef2b7db7be2c3e328a97536 \
npx vitest run --maxWorkers=1 --no-file-parallelism --pool=threads
这里的 JWT 值仅用于一次性、无外部网络的测试容器,不是网站实际使用的密钥。--rm 会在退出后移除该临时容器,本命令没有挂载在线数据。
结果
Test Files 1 passed (1)
Tests 47 passed (47)
Duration 8.09s
覆盖范围来自项目自带测试,包括账号、文章、分类、标签、菜单、自定义页面及留言审核等接口。它不等同于浏览器全流程测试、安全审计或压力测试。
复盘
这次至少包含两个不同的问题:测试工作进程在当前镜像环境中崩溃,以及镜像缺少测试配置所需的环境变量。前者通过改变运行方式避开,但没有进一步定位底层根因;后者则由源码与 Dockerfile 对照确认。
项目来源:eooce/eooce-blog。
