You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitLab CI运行容器时出现exec: "sh": executable file not found in $PATH错误,请求排查问题根源(Dockerfile或GitLab CI配置)

问题根源与解决方案

你的错误是Dockerfile特性与GitLab CI配置共同作用导致的,下面具体拆解并给出解决办法:

为什么会报错?

1. Dockerfile的核心限制:scratch镜像无任何系统工具

你的最终镜像基于scratch——这是一个完全空的基础镜像,不包含任何操作系统文件,既没有sh这类shell解释器,也没有ls、cp这类基础命令。

你本地用docker run --rm -ti ...能正常运行,是因为这个命令默认会触发镜像的ENTRYPOINT(也就是你的/usr/bin/app-cli二进制文件),不需要依赖shell。

2. GitLab CI的运行逻辑需要shell

在你的GitLab CI配置里:

  • 你设置了entrypoint: [""],覆盖了镜像原本的入口命令
  • GitLab CI执行script段时,默认会尝试调用sh -c "你的脚本内容"来解析执行命令(比如这里的ls)

但你的容器里根本没有sh,自然会抛出exec: "sh": executable file not found的错误。

两种解决方案,根据你的需求选择

方案一:如果Validation job只需要测试CLI工具功能

如果你的验证步骤不需要执行ls这类shell命令,只是要运行你的app-cli做校验,那可以直接调用二进制文件,不需要修改Dockerfile,调整.gitlab-ci.yml即可:

stages:
  - validation
validation:
  image: gitlab.mycompany.net:4567/myteam/app-cli:latest
  stage: validation
  rules:
    - if: '$CI_MERGE_REQUEST_IID'
  script:
    - /usr/bin/app-cli [你的测试参数]  # 比如/app-cli --version或者你的校验命令

这里不需要设置entrypoint: [""],让GitLab CI把script里的内容作为参数传给镜像原本的ENTRYPOINT即可。

方案二:如果确实需要在容器里执行shell命令

如果你的验证步骤必须用到ls、echo这类基础命令,那你需要修改Dockerfile,把最终镜像从scratch换成一个最小的带shell的镜像,比如alpine:latest(只有几MB大小,几乎不增加镜像体积):

FROM golang:1.16-alpine AS builder
ENV \
 OUTDIR='/out' \
 GO111MODULE='on'
WORKDIR /app
COPY go.mod /app/
COPY go.sum /app/
RUN go mod download
COPY . /app/
RUN CGO_ENABLED=0 GOBIN=${OUTDIR}/usr/bin/ go install .

# 替换scratch为alpine
FROM alpine:latest
COPY --from=builder /out/ /
ENTRYPOINT ["/usr/bin/app-cli"]

修改后,你的镜像会自带sh和基础工具,GitLab CI里的script: - ls就能正常执行了。

内容的提问来源于stack exchange,提问作者Roy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:49:08