Docker中Yarn脚本无法找到本地二进制文件:PATH路径异常排查
你推测的完全正确,这是Yarn v1.x的一个已知bug:当通过.yarnrc的--modules-folder配置将node_modules放到非工作目录的位置时,yarn run在生成执行脚本的子进程时,只会将当前工作目录(/app)下的node_modules/.bin注入到PATH环境变量中,完全忽略了你配置的自定义模块目录(/node_modules/.bin)。
而yarn bin能返回正确路径是因为它直接读取你的配置,但yarn run的子进程PATH逻辑没有同步这个配置,导致shell找不到vite这类二进制文件。
另外你提到修改NODE_PATH没用,是因为NODE_PATH仅作用于Node.js的模块解析(比如require()查找),不影响shell的命令查找,shell找二进制文件只看PATH,所以改它解决不了问题。
1. 脚本内手动注入PATH
直接在package.json的脚本开头,把/node_modules/.bin追加到PATH中:
{ "scripts": { "dev": "PATH=$PATH:/node_modules/.bin vite dev --host" } }
这样每次执行脚本时,shell会先更新PATH,就能找到正确的二进制文件。
2. 容器全局设置PATH
如果不想每个脚本都重复写PATH配置,可以在Dockerfile中添加环境变量,把/node_modules/.bin加入系统全局PATH:
ENV PATH="/node_modules/.bin:${PATH}"
这样不管是yarn run还是直接执行二进制命令,shell都能找到对应文件。
3. 升级Yarn版本
Yarn v2及以上(Berry分支)已经修复了这个自定义模块目录的PATH注入问题,对非工作目录的node_modules支持更完善。如果项目兼容的话,升级到Yarn Berry可以彻底解决这个问题。
内容的提问来源于stack exchange,提问作者minnow

