GitLab Pipeline运行docker compose时容器ENTRYPOINT脚本未运行
问题现象
容器配置了启动自动执行的shell脚本,本地执行docker compose --force-recreate --build -d时功能正常;代码推送到GitLab通过Pipeline执行相同构建启动命令时,脚本无法正常运行。
异常特征:
- 本地环境下删除Dockerfile中
/bin/bash ./entrypoint.sh行后重新输入,再执行重建命令,shell脚本可正常执行 - Pipeline执行失败时,本地Git检测不到任何文件变更,无内容可推送至仓库
- 已参考StackOverflow行尾符相关排查思路,尝试Daniel Howard、P.J.Meisch、Ryan Allen公开的解决方案,均未生效
- 当前使用的GitLab Runner为部署在本地物理机的专用Runner,非平台共享Runner
相关配置
Dockerfile
# Setup SQL Server 2019 FROM mcr.microsoft.com/mssql/server:2019-latest ENV SA_PASSWORD=Banana100 ENV ACCEPT_EULA=Y ENV MSSQL_PID=Developer USER mssql #Copy test database and create DB script to image working directory WORKDIR /usr/src/app COPY . /usr/src/app EXPOSE 1433 ENTRYPOINT /bin/bash ./entrypoint.sh
entrypoint.sh
脚本作用为执行SQL文件完成数据库创建与恢复:
# /opt/mssql/bin/sqlservr & /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P FBuilder*09 -d master -i createDB.sql /opt/mssql/bin/sqlservr & /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -d master -i createDB.sql while true; do sleep 1000; done
docker-compose.yml
version: "3" services: fb_db: container_name: test_fbdb build: ./test.environment ports: - "5002:1433"
.gitlab-ci.yml
.ci_server: tags: - ci stages: - build - test variables: SOLUTION_NAME: FBSVC.sln before_script: - Set-Variable -Name "time" -Value (date -Format "%H:%m") - echo ${time} - echo "started by ${GITLAB_USER_NAME}" build: stage: build extends: - .ci_server script: - echo "Restoring project dependencies..." - $Env:Path += ";C:\nuget" - nuget restore - echo "Preparing development environment" - copy "D:\CI_TestDB\FormulaBuilder\FormulaBuilder.bak" "D:\Project Files\Gitlab-Runner\builds\_1ZgTgcF\0\water-utilities\formula-builder\test.environment" - docker compose up --force-recreate --build -d - echo "Publishing project..." - $Env:Path += ";C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin" - msbuild FBSVC.sln /p:DeployOnBuild=true /p:PublishProfile=CI_IntegrationTest - echo "Build stage completed successfully!" only: - merge_requests test: stage: test variables: GIT_STRATEGY: clone extends: - .ci_server script: - echo "Installing dev dependencies..." - npm ci - echo "Running tests..." - npm run cy:test dependencies: - build only: - merge_requests
2022年6月24日更新排查进展
- 已将Dockerfile中的ENTRYPOINT修改为exec格式:
ENTRYPOINT [ "/bin/bash", "-c", "./entrypoint.sh" ],问题仍然存在 - VS Code右下角显示本地Dockerfile行尾序列为LF,但检查Pipeline拉取的Dockerfile发现行尾序列变为CRLF
- 多次执行
git config --global core.autocrlf input配置,从仓库拉取文件时仍会自动转换行尾符 - 当前临时规避方案:将数据库环境构建相关的文件夹移出构建上下文,但每次都需要重写Dockerfile中的ENTRYPOINT行才能正常运行
根因说明
CRLF与LF的行尾符差异就是故障核心原因。
Linux环境下的bash无法识别行尾携带的\r(CR字符):当ENTRYPOINT行或entrypoint.sh脚本被自动转换为CRLF结尾时,行尾的\r会被识别为命令/文件路径的一部分,系统会查找名称带\r后缀的脚本文件,或将\r作为非法参数传入,直接导致启动命令执行失败。
本地删除ENTRYPOINT行重输后临时生效,本质是重输的行被本地编辑器保存为LF结尾,覆盖了原有CRLF行,但仓库中存储的文件仍为CRLF格式,Runner拉取代码时自然复现故障。
解决方案
按以下步骤操作即可彻底修复,不需要反复修改ENTRYPOINT行:
- 仓库层面强制锁定行尾规则
在仓库根目录新建.gitattributes文件,写入以下规则,从版本控制层面强制指定Linux相关脚本、配置文件必须使用LF行尾,不依赖本地或Runner的全局git配置:
将该文件提交到仓库后,任何环境拉取上述类型文件时,都会被自动转换为LF格式,不会再出现CRLF问题。# 强制所有shell脚本使用LF行尾 *.sh text eol=lf # 强制Dockerfile使用LF行尾 Dockerfile text eol=lf # 强制SQL脚本使用LF行尾,避免sqlcmd执行异常 *.sql text eol=lf - 修正仓库中已存在的CRLF文件
提交.gitattributes后,在本地仓库根目录执行以下命令,重置git索引并重新生成符合行尾规则的工作区文件:git rm --cached -r . git reset --hard - Dockerfile增加容错逻辑
在COPY指令后增加行尾修正、执行权限赋予逻辑,彻底规避行尾符带来的执行异常,同时将ENTRYPOINT改为绝对路径的exec格式,减少路径解析问题:COPY . /usr/src/app # 移除entrypoint.sh中可能存在的\r字符 RUN sed -i 's/\r$//' ./entrypoint.sh # 给脚本加执行权限 RUN chmod +x ./entrypoint.sh EXPOSE 1433 # 使用绝对路径exec格式启动 ENTRYPOINT ["/bin/bash", "/usr/src/app/entrypoint.sh"] - 校验Runner环境的git配置
由于Runner部署在Windows系统上,需要确认Runner执行用户的git配置没有强制开启CRLF转换:登录Runner所在机器,切换到Runner服务的运行用户,执行git config --global core.autocrlf,如果返回值为true,执行以下命令修改为input:git config --global core.autocrlf input
内容的提问来源于stack exchange,提问作者jdistro07
相关产品推荐
相关产品推荐

