Dockerfile中ENTRYPOINT未识别WORKDIR致可执行文件找不到的问题
我的Dockerfile内容如下:
FROM mcr.microsoft.com/dotnet/runtime-deps:7.0.10-alpine3.18-amd64 ARG APP_DIR=/var/lib/app/ WORKDIR $APP_DIR # etc. ENTRYPOINT ["MyApp"] # 可执行文件位于/var/lib/app/MyApp
运行容器时出现以下错误:
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "MyApp": executable file not found in $PATH: unknown.
我已经指定了WORKDIR,为什么还是找不到该可执行文件?(使用ENTRYPOINT ["/var/lib/app/MyApp"]时可正常运行,因此不存在权限问题。)
核心原因
Docker的WORKDIR仅负责设置容器启动后的当前工作目录,但它不会自动将该目录添加到系统的$PATH环境变量中。
当你使用**exec格式(数组形式)**的ENTRYPOINT/CMD时,Docker会直接调用操作系统的exec系统调用,不会启动shell进程。这种情况下,系统只会在$PATH环境变量列出的目录中查找可执行文件——哪怕当前工作目录下存在目标文件,只要不在$PATH的路径列表里,就会提示找不到。
两种解决办法
将工作目录添加到
$PATH
在Dockerfile中新增ENV指令,把工作目录加入系统路径:FROM mcr.microsoft.com/dotnet/runtime-deps:7.0.10-alpine3.18-amd64 ARG APP_DIR=/var/lib/app/ WORKDIR $APP_DIR ENV PATH="$PATH:$APP_DIR" # 新增该行,将工作目录加入系统路径 # etc. ENTRYPOINT ["MyApp"]这种方式保留了exec格式的优势(信号处理正常,容器能优雅停止),是更推荐的方案。
改用shell格式的
ENTRYPOINT
将数组形式的指令改为普通字符串形式,Docker会启动shell来执行命令,而shell默认会把当前目录(.)加入$PATH,因此能找到当前工作目录下的MyApp:ENTRYPOINT MyApp # 去掉数组括号,使用shell格式注意:这种方式会让容器的PID 1进程变成shell而非你的应用进程,可能导致容器无法优雅接收停止信号(比如
docker stop时需要等待超时),仅建议在特殊场景下使用。
内容的提问来源于stack exchange,提问作者lonix

