Docker 运维SWES · 技术记录

Docker 内运行 API 测试失败:从进程崩溃排查到 47 项通过

记录日期:2026-10-19(多伦多)。本次排查针对 eooce-blog 的特定镜像,不是所有 Node.js / Vitest 问题的通用修复。 现象 直接在镜像内执行 npm test 时,出现 Node 原生断言和子进程通信错误: RemoveEnvironmentCleanupHook

记录日期: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。

感谢阅读 · 保持好奇,认真记录。浏览更多文章 ↗