npm脚本执行docker命令失效,使用$(pwd)挂载卷找不到package.json
问题根源
npm在Windows环境下默认使用cmd.exe执行脚本,cmd不支持$(pwd)这类Unix shell的变量替换语法,会直接把$(pwd)作为字符串传递给docker,导致挂载路径失效,容器内部找不到对应的package.json文件。你在Git Bash中直接执行命令有效,是因为Git Bash会提前解析$(pwd)替换为实际的本地路径。
解决方案
方案一:指定npm使用Git Bash执行脚本(适合团队都用Windows+Git Bash的场景)
- 在项目根目录新建
.npmrc文件,添加如下配置(路径替换为你本地Git Bash的实际安装路径):
script-shell = "C:\\Program Files\\Git\\bin\\bash.exe"
- 修改package.json的scripts配置:
{ "scripts": { "test": "MSYS_NO_PATHCONV=1 docker run -it -v $(pwd):/app -w /app node:slim bats test/**/*.bats", "test-ci": "MSYS_NO_PATHCONV=1 docker run -it -v $(pwd):/app -w /app node:slim bats --formatter junit -T test/**/*.bats" } }
配置完成后直接执行npm test即可正常运行。
方案二:使用Node脚本封装执行(跨平台通用,无依赖)
该方案无需修改npm配置,兼容Windows、macOS、Linux全平台,不需要依赖本地shell类型。
- 在项目根目录新建
run-docker-test.js文件,内容如下:
const { execSync } = require('child_process'); // 统一转换为Unix风格路径 const workDir = process.cwd().replace(/\\/g, '/'); const isWin = process.platform === 'win32'; // 拼接执行命令 const cmd = [ isWin ? 'set MSYS_NO_PATHCONV=1 &&' : '', 'docker run', // CI环境可以去掉-it参数 process.env.CI ? '' : '-it', `-v ${workDir}:/app`, '-w /app', 'node:slim', // 根据场景选择执行的测试命令 process.env.CI ? 'bats --formatter junit -T test/**/*.bats' : 'bats test/**/*.bats' ].filter(Boolean).join(' '); try { execSync(cmd, { stdio: 'inherit' }); process.exit(0); } catch (err) { process.exit(err.status || 1); }
- 修改package.json的scripts配置:
{ "scripts": { "test": "node run-docker-test.js", "test-ci": "CI=true node run-docker-test.js" } }
两种方案都完全不需要硬编码本地路径,符合你的需求。
内容的提问来源于stack exchange,提问作者Poat
相关产品推荐
相关产品推荐

