如何在容器内部sh脚本执行失败时让docker run命令同步返回失败
根因说明
docker run 默认会将容器内1号进程的退出码原样返回,出现脚本执行失败但docker命令返回0的情况,通常由以下3个原因导致:
- 脚本匹配逻辑有误,实际未触发
exit 1分支:你脚本中grep "Docker Version"的匹配规则要求V大写,而官方docker版本输出为Docker version x.x.x(v小写),会导致匹配失败分支未按预期触发 - 镜像的ENTRYPOINT封装脚本拦截了退出码:如果你的镜像自定义了ENTRYPOINT启动脚本,且没有用
exec启动后续命令,1号进程会是入口脚本,你执行的test.sh退出码不会传递给容器主进程,docker只能拿到入口脚本的0退出码 - 脚本路径/调用权限问题:容器默认工作目录下不存在test.sh,或脚本无执行权限,导致sh解析器报错退出但你未感知到
修复方案
1. 优化test.sh脚本
修正匹配逻辑,明确指定解析器,消除隐式判断问题,优化后代码如下:
#!/bin/sh echo "Validating Docker Installation" # 直接把命令写在if判断中,避免$?捕获错误 if which docker > /dev/null 2>&1 then # 加-i参数忽略大小写匹配,避免大小写不一致导致匹配失败 if docker --version | grep -i "Docker Version" > /dev/null 2>&1 then echo "Docker installed successfully" exit 0 else echo "Docker version check failed" exit 1 fi else echo "Docker not installed" exit 1 fi
构建镜像时在Dockerfile中添加执行权限配置:
RUN chmod +x /opt/test.sh
(请将/opt/test.sh替换为你镜像中脚本的实际存放路径)
2. 调整gitlab-ci的docker run调用逻辑
覆盖镜像默认ENTRYPOINT,使用脚本绝对路径调用,避免退出码被拦截:
test_job: stage: test script: - docker pull $DOCKER_REGISTRY/$DOCKER_REPO:$BUILD_VERSION - docker run --rm --entrypoint="" $DOCKER_REGISTRY/$DOCKER_REPO:$BUILD_VERSION sh /opt/test.sh
3. 本地验证方法
你可以在本地执行以下命令确认退出码传递正常:
docker run --rm --entrypoint="" $DOCKER_REGISTRY/$DOCKER_REPO:$BUILD_VERSION sh /opt/test.sh # 打印退出码,脚本失败时应返回1 echo $?
内容的提问来源于stack exchange,提问作者brijesh kalavadia
相关产品推荐
相关产品推荐

