宿主机装不了 Playwright Chromium 时如何用 ./cops 在 Docker 容器里运行 career-ops
【免费下载链接】career-opsOpen-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications — runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravity…)项目地址: https://gitcode.com/GitHub_Trending/ca/career-ops
career-ops 的 PDF 渲染、门户扫描和 liveness 检查都依赖无头 Chromium,原生安装需要在宿主机上执行npx playwright install chromium(见 docs/SETUP.md 的 "PDF rendering (one-time)" 一节)。但有些宿主机装不了它:DOCKER.md 明确列出的典型情况是 Ubuntu 26.04、没有playwright-drivershell 的 NixOS、以及管控严格的企业笔记本。Dockerfile 里的注释给出了原因——宿主机内核若阻止 Playwright 的 Chromium 安装器,而浏览器随镜像内置、在镜像自己的用户态下运行时,容器方案就能跑通。
这篇文章对应的就是官方给出的替代路径:不修宿主机环境,把整个 career-ops 放进 Docker 容器运行,通过项目根目录的./cops包装器执行所有命令,功能不裁剪——PDF 生成、扫描器、liveness 检查器、Go 写的 dashboard、批量 worker、更新系统都在容器内运行。
先看懂容器为什么能绕过 Chromium 安装问题
三个文件决定了整套方案的行为,值得在动手前扫一眼:
- Dockerfile:基础镜像是
mcr.microsoft.com/playwright:v1.62.1-jammy,Chromium 已预装,并且构建时会把playwright固定安装到1.62.1,与基础镜像自带的 Chromium 版本对齐。镜像内还装了 Go 1.23.4(dashboard 用)和 LaTeX 相关包(generate-latex.mjs用)。项目源码不在构建期复制进镜像,运行时才挂载,所以你在宿主机的修改在容器里立即生效。 - docker-compose.yml:把整个项目目录 bind-mount 到容器内的
/app;node_modules放在命名卷career-ops-node-modules里,避免宿主机与容器之间的 ABI 不匹配(注释里点明场景:宿主机是装不了 Playwright 的 ubuntu26.04,镜像是 jammy)。另外shm_size: "1gb"是 Chromium 需要的,默认 64M 的/dev/shm不够。 - cops:一个薄包装脚本。它先把命令映射到
docker compose exec;遇到doctor、scan、pdf、liveness这类已知的 npm script 就转发成npm run <name>,其余子命令原样在容器内执行。执行前它会检查容器是否在跑,没跑就先docker compose up -d把它拉起来。
也就是说,日常纪律只有一条:所有 career-ops 命令都走./cops,不要在宿主机上直接跑node或npx——宿主机上的 Node 没有可用的 Chromium,这正是排查清单里 "Playwright still complains" 的根因。
准备条件
- Docker Engine 24+,带 Compose 插件。用
docker compose version确认插件可用。 - 约 2 GB 空闲磁盘容纳镜像(基础镜像约 1.5 GB,首次构建后要等几分钟)。
- 你已经在本地有一份 career-ops 项目目录,命令都在项目根目录下执行。
首次启动与验证
在项目根目录下依次执行:
./cops up # 构建镜像(首次需要几分钟)并启动容器 ./cops doctor # 确认 node + playwright + chromium + go 都在./cops up之后容器会在后台保持运行,后续每次./cops调用都即时进入,不用重复启动。
验证的关键是doctor里的 Playwright 检查。看 doctor.mjs 的实现就知道它不是查文件路径——它会真的chromium.launch({ headless: true })启动一次浏览器,通过则打印Playwright chromium installed,失败则打印Playwright chromium not installed并提示Run: npx playwright install chromium(该修复提示针对的是原生环境;容器内这条不应该出现,出现了就说明你在宿主机上跑 doctor 而不是./cops doctor)。整个 doctor 全部通过时退出码为 0,并给出Result: All checks passed;有任何失败项则退出码为 1 并列出问题清单。
日常用法:一切都经 ./cops 转发
cops 会把任何命令转发进容器,DOCKER.md 给出的常用对照:
| 任务 | 命令 |
|---|---|
| 健康检查 | ./cops doctor |
| 验证 pipeline | ./cops verify |
| 生成 PDF | ./cops pdf output/cv.html output/cv.pdf |
| 扫描门户 | ./cops scan |
| 检查链接存活 | ./cops liveness <url> |
| 合并 tracker | ./cops merge |
| 去重 tracker | ./cops dedup |
| 状态归一化 | ./cops normalize |
| 更新检查 / 执行 / 回滚 | ./cops update:check/./cops update/./cops rollback |
| 交互式 shell | ./cops shell |
| 原始 node 脚本 | ./cops node check-liveness.mjs <url> |
未识别的子命令会直接落进docker compose exec,所以任意命令都能用,例如:
./cops npm test ./cops bash -c 'find reports -name "*.md" | wc -l'构建 dashboard 的完整命令也走这个通道:
./cops bash -c 'cd dashboard && go build -buildvcs=false -o career-dashboard . && ./career-dashboard --path ..'API key 的处理与原生一致:写进项目根目录的.env,或在执行./cops的那个 shell 里 export。compose 文件会转发GEMINI_API_KEY、ANTHROPIC_API_KEY、OPENAI_API_KEY三个变量进容器(空值忽略)。DOCKER.md 给的示例:
echo "GEMINI_API_KEY=..." >> .env ./cops gemini:eval生命周期与更新
./cops up # 启动(幂等,可重复执行) ./cops down # 停止并删除容器(卷保留) ./cops rebuild # 完整重建(Dockerfile 或依赖变更后使用) ./cops logs # 跟踪容器日志数据不用担心丢失:项目根目录下的所有东西都在宿主机文件系统上——cv.md、config/profile.yml、modes/_profile.md、portals.yml、data/applications.md、data/pipeline.md、data/scan-history.tsv、reports/、output/、interview-prep/、jds/。容器内不存重要数据,所以./cops down是安全的。
更新流程与原生相同:
./cops update:check ./cops update唯一的差别是:如果更新导致package.json依赖变化,需要跑一次./cops rebuild刷新持有node_modules的镜像层。
常见排查
DOCKER.md 的 Troubleshooting 一节列出四种情况,都与"宿主机装不了 Chromium"这条路径直接相关:
docker: not found— 还没装 Docker。先安装 Docker Engine 和 Compose 插件,再继续本文步骤。- Playwright 仍然报错— 你跑的是宿主机的 Node 而不是容器里的。解决办法就是本文反复强调的:一切走
./cops。 - 生成的文件出现权限错误— 容器默认以 root 运行,宿主文件可能变成 root 属主。两个处理办法(都是对你自己 checkout 的操作):执行一次
sudo chown -R "$USER" .把属主改回自己;或在docker-compose.yml里加user: "${UID}:${GID}"(先在 shell 里 exportUID/GID)。注意chown会改动项目目录下所有文件的属主,确认目录范围后再执行。 - 首次构建慢— 基础镜像约 1.5 GB,属正常现象;后续构建复用层缓存,几秒内完成。
边界说明
这条路径不改变任何文件布局:.dockerignore会把.env、reports/*.md、jds/*等生成物和个人数据挡在构建上下文之外,所以镜像只包含运行所需的依赖,报告、CV、tracker 照常落在宿主机上。如果某天宿主机能直接装 Chromium 了,原生方式(宿主机npm install+npx playwright install chromium)和容器方式可以并存,区别只是前者不需要./cops转发。
【免费下载链接】career-opsOpen-source AI job search: scan job portals, evaluate listings into a structured A-H report with a global 1-5 score, tailor your CV, track applications — runs locally in your AI coding CLI (Claude Code, Codex, OpenCode, Antigravity…)项目地址: https://gitcode.com/GitHub_Trending/ca/career-ops
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考