Docker容器启动时报错:exec user process caused: no such file or directory怎么办?
今天用Docker部署Node项目时遇到个怪问题,容器启动就报错“exec /bin/sh: exec user process caused: no such file or directory”。我检查了Dockerfile里的CMD指令,明明写的是node app.js啊。
尝试在docker run里加了-it参数也没用,还特意用docker exec进容器手动执行node app.js,发现确实能跑起来。难道是我的Dockerfile哪里配置错了?附上Dockerfile片段:
FROM node:16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD node app.js
更奇怪的是,之前同样的Dockerfile在另一个项目里能正常工作。这个项目的app.js权限没问题,用ls -l看权限是-rw-r–r–。难道是alpine镜像的路径问题?或者需要额外安装什么依赖?
CMD node app.js,这是 shell form 的写法,Docker 会默认用/bin/sh -c去执行它。但 Alpine 镜像的基础镜像里可能没有装sh或者路径不对,就会报那个“no such file or directory”的错,尤其是当你看到 exec 报的是/bin/sh找不到的时候,基本可以确定是这个问题。虽然你说手动 exec 进去能跑 node app.js,那是因为容器启动后环境已经加载了,但初始 entrypoint 执行阶段可能连 shell 都没准备好。
解决方法很简单:改成 exec form 写法,绕过 shell 解析。
把这行:
改成:
记得转义,数组里的每个参数都得是独立字符串。这样 Docker 就会直接调用 node 可执行文件,不再依赖 /bin/sh,也就不会触发那个路径问题。
另外建议检查一下你的 app.js 文件有没有 Windows 换行符(CRLF),有时候从 Windows 编辑器复制过去,Linux 下第一行会识别成带 ^M 的乱码命令,也会导致找不到文件。可以用 dos2unix 处理下,或者在 COPY 之后加个 tr 命令清理:
不过优先改 CMD 成数组形式,大概率就解决了。这个坑我之前也踩过,看着一样的 Dockerfile,换个项目就不行,八成就是 shell form 的隐式依赖在作祟。
CMD node app.js,这是 shell form,Docker 会默认用/bin/sh -c去执行它。但 alpine 镜像比较精简,有些版本连/bin/sh都可能有问题,或者你的系统是 Windows 环境构建的,换行符搞出了幺蛾子。先说解决方案,改成 exec form 就完事了:
这种写法不依赖 shell,直接调用 node 进程,绕过 /bin/sh 的查找问题。而且能避免 Windows 下 CRLF 换行符导致的 “no such file or directory” 错误(看起来文件存在,但实际命令变成 node app.jsr,Linux 找不到)。
另外检查下你的项目是不是在 Windows 或 Git 提交时自动转了换行符。可以在 .gitattributes 里加一行:
确保所有脚本文件都是 LF 换行。再一个建议,本地开发时如果用 VS Code,右下角看看是不是 CRLF,手动切回 LF 试试。
你之前另一个项目能跑,可能是 Node 版本不同或者没走 shell 路径。JS里面这种环境差异太常见了,别看代码一样,底层系统一变就出事。赶紧改 CMD 写法,99% 能解决。