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

自托管GitLab CI构建Docker镜像时无法读取根目录CHANGELOG.md问题

问题根本原因

这个报错和相对路径写法本身没有关系,是Docker构建的上下文机制限制导致的:

  • 你执行docker build命令时最后传入的./build/image1是本次构建的上下文根路径,Docker只会把这个目录下的所有文件打包发送给构建进程,上下文边界外的文件(包括上层build目录、仓库根目录下的CHANGELOG.md)根本不会被加载到构建环境里。Docker从安全机制上就禁止构建过程访问上下文以外的宿主文件,不管你在Dockerfile里写多少层../向上跳,只要跳出了上下文边界,就会被判定为文件不存在。
  • 你之前写的../../CHANGELOG.md是按照Dockerfile自身所在位置计算的路径,但Dockerfile里的所有相对路径,实际都是相对于构建上下文根解析的,不是相对于Dockerfile的磁盘存储位置解析,这也是很多人容易踩的认知误区。
可行解决方法

选任意一种符合你需求的方案即可:

  • 方案1:调整构建上下文为仓库根目录(最推荐,无额外冗余操作)
    修改gitlab-ci.yaml里的docker build命令,把上下文路径改成仓库根目录,同时显式指定Dockerfile的位置:
    # 构建image1的命令,最后面的 . 代表以当前工作目录(仓库根目录)为构建上下文
    docker build --network host -f ./build/image1/Dockerfile -t $VAL_IM .
    
    对应修改Dockerfile里的grep路径,把原来的../../CHANGELOG.md直接改成./CHANGELOG.md即可,因为此时上下文根就是仓库根,直接就能读到根目录下的更新日志文件。构建image2、image3时同理,替换-f参数后的Dockerfile路径就行,上下文始终用仓库根目录。
  • 方案2:CI阶段提前传入版本号(适合版本号不需要长期存在于镜像构建上下文的场景)
    不需要在Dockerfile内部读CHANGELOG文件,直接在gitlab-ci脚本里提前提取好版本号,通过构建参数传给Docker:
    # 先在CI环境里从根目录CHANGELOG.md提取版本号,替换成你实际用的grep匹配规则
    export IMAGE_VER=$(grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+' CHANGELOG.md | head -n1)
    # 构建时把版本号作为build-arg传入
    docker build --network host --build-arg IMAGE_VER=$IMAGE_VER -t $VAL_IM ./build/image1
    
    对应在Dockerfile开头加一行ARG IMAGE_VER,后续直接用$IMAGE_VER变量就行,完全不需要处理文件路径问题。
  • 方案3:构建前临时拷贝文件(适合不想调整原有构建逻辑的场景)
    在执行docker build之前,先把根目录的CHANGELOG.md拷贝到当前构建的image子目录里:
    # 构建image1前执行
    cp CHANGELOG.md ./build/image1/
    docker build --network host -t $VAL_IM ./build/image1
    
    然后把Dockerfile里的grep路径改成./CHANGELOG.md就能正常读取了,注意如果不需要把这个文件打进最终镜像,可以在Dockerfile的对应执行阶段结束后删掉,或者在.dockerignore里做对应配置避免冗余。

注意:不要尝试通过调整../的层数绕过上下文限制,Docker的上下文隔离是强制的安全机制,不存在放开限制的配置项,所有要在Dockerfile里访问的文件,必须放在构建上下文目录范围内。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 05:21:24