Docker Git 上下文构建报 /.git not found
Git 上下文默认不保留 .git,忽略规则例外不能恢复它。用预定义参数保留构建所需仓库信息,或明确选择路径上下文,并限制最终产物。
同一份 Dockerfile 在本地目录构建时能读取 .git,改为 Git URL 或 GitHub Actions 的默认 Git 上下文后,COPY .git 却失败:
failed to compute cache key: "/.git" not found: not found
即使在 .dockerignore 中给 .git 加了例外,目录也可能仍然不存在。使用 Git 上下文时,BuildKit 默认不保留检出的 .git 目录;忽略规则不能恢复已经被移除的输入。
下文限定为 BuildKit 的 Git 上下文。不适用于把宿主机目录作为 . 传入的构建,也不处理另一构建阶段下载后误带入最终镜像的仓库文件。
先确认真正传给构建器的上下文
命令最后的上下文参数为 Git 仓库 URL 时,是 Git 上下文;以本地目录为参数时,是路径上下文。-f Dockerfile 只选择构建定义,不能据此判断源码来自哪里。
docker/build-push-action 默认使用 Git 上下文,通常由触发工作流的 Git 引用决定。前面添加了 checkout 步骤,并不自动改变构建动作使用的上下文。应查看构建动作的 context 输入和实际日志,而不是只看工作区里能否列出 .git。
如果构建仍从远端 Git 引用取文件,前置步骤在工作区修改的 .dockerignore 或源码也不会成为这个上下文的输入。需要这些修改时,应明确选择路径上下文;这是输入来源的选择,不能只靠调整 COPY 路径修复。
Git 上下文确实需要仓库信息时,明确保留它
在现有构建调用中增加 BUILDKIT_CONTEXT_KEEP_GIT_DIR=1。下面的仓库地址、引用和镜像标签都是占位示例,需替换为可信的实际项目:
docker buildx build \
--build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 \
--progress=plain \
--load \
-t myapp:git-check \
'https://github.com/example/example-app.git#main'
示例用 --load 将单平台结果装入本地镜像库;已有多平台发布流程应保留原输出方式,不要为这一项配置改成单平台。项目原有 Dockerfile 路径、其他构建参数和平台选择也应保持一致。
这是 BuildKit 预定义的构建参数,不是让应用在运行时读取的环境变量。现有 GitHub Actions 构建步骤可在 with 下的 build-args 列表中加入:
build-args: |
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
这段是合入现有步骤的配置片段,不是完整工作流。已有其他参数时追加一行,不能覆盖原列表。不要为了获取提交号,将仓库访问令牌改成普通 build argument。
保留 .git 后仍失败时,再核对上下文子目录、Dockerfile 实际工作目录以及适用的 .dockerignore 规则。如果构建上下文选在仓库的子目录,不要假设仓库根目录的一切内容都在当前输入范围内。也不要为了看到 .git,把整个忽略文件删掉。
构建需要 Git,不代表最终镜像也要携带 Git
若只是把提交号写入构建产物,可以在构建阶段使用仓库信息,再只复制发布产物。以下是说明这个边界的完整 Dockerfile 示例,要求可信 Git 上下文且没有把所需文件排除:
# syntax=docker/dockerfile:1
FROM alpine:3.22 AS revision
RUN apk add --no-cache git
WORKDIR /src
RUN --mount=target=. \
mkdir -p /out \
&& git rev-parse HEAD > /out/revision.txt
FROM scratch
COPY --from=revision /out/revision.txt /revision.txt
将它配合前面的保留参数使用。RUN --mount=target=. 在该指令中提供上下文;输出写到挂载之外的 /out,最终阶段只复制文本文件。这个示例镜像是文件产物,不包含可启动的应用,不能用运行成功来验收它。
实际项目应保留自己的构建命令、运行基础镜像与入口,只沿用输入和产物分离的做法。不要把 .git 整体复制到最终镜像,再用后续层删除来宣称历史内容已经消失。
需要工作区文件时,切换路径上下文
如果构建必须使用 checkout 后生成或修改的文件,在现有工作流中保留正确的 checkout 步骤,并显式设置构建动作:
context: .
此时才应按工作区实际文件和 .dockerignore 核对 .git 是否可见。BUILDKIT_CONTEXT_KEEP_GIT_DIR 不能替路径上下文下载缺失的 Git 数据,也不能让被忽略的文件自动出现。
另外,保留 .git 不等于拥有完整历史。Git 上下文采用浅克隆,依赖完整历史或标签的版本计算可能仍有不同结果。这里只解决目录被默认移除;不要用 git rev-parse HEAD 成功来证明所有 git describe、历史遍历或标签规则都已满足。
验收提交号与最终内容
修改前保存原工作流、Dockerfile 与可回退镜像引用。先在允许构建的隔离环境核对 .git 相关步骤不再报缺失,并确认产出的提交号对应实际选定的 Git 引用。移动分支会继续变化,要求可追溯构建时应按项目策略使用确定的提交。
同时检查最终产物没有多出仓库历史或不需要的配置文件。如果只是为了提交号而引入了整套仓库数据,缩小复制范围后再交付。恢复原参数或上下文设置时,也要恢复配套构建定义;已经推送出去的旧镜像不会因工作流回退而自动删除。


