如何使git clone与Docker缓存配合使用?

时间:2019-03-05 12:53:03

标签: git docker caching

当我两次克隆存储库时,例如:

git clone <repo_X> --depth 1 clone1
git clone <repo_X> --depth 1 clone2

然后进行差异

diff -r clone1 clone2

这显示出差异:

Binary files clone1/.git/index and clone2/.git/index differ
...
diff -r clone1/.git/logs/HEAD clone2/.git/logs/HEAD
...
diff -r clone1/.git/logs/refs/remotes/origin/HEAD 
...

似乎在文件中记录了克隆的时间。

我想向Docker映像添加一些存储库。当文件未更改时,Docker将使用其缓存。不幸的是,在克隆之后,Docker总是由于更改的文件而使缓存无效。

  1. 是否可以在完全相同的文件中包含两个仓库的克隆结果? (注意:我不想删除.git目录,因为我希望能够在图像内部使用git来检查存储库的版本。)

  2. 在进行缓存时,是否可以让Docker忽略.git文件夹(请注意,仍然必须将.git文件夹添加到映像中,所以.dockerignore不是一个选择吗?)

2 个答案:

答案 0 :(得分:1)

您可以使用新的 Docker 的 BuildKit 功能 --mount=cache。 Dockerfile 的玩具示例:

FROM ubuntu
RUN --mount=type=cache,target=/var/cache/apt \
    apt update && apt upgrade -y && apt install -yq git
RUN echo A00
RUN --mount=type=cache,target=/tmp/git_cache/ \
    git clone --depth=1 https://github.com/qtox/qtox/ /tmp/git_cache/qtox/; \
    cd /tmp/git_cache/qtox/ && git pull && cp -r ./ /tmp/my_qtox/
RUN echo B00

以上dockerfile可以通过命令构建:

sudo env DOCKER_BUILDKIT=1 docker build -f Dockerfile .

注意 DOCKER_BUILDKIT=1 环境变量的存在,有必要在 docker build 中启用所有 BuildKit 的功能。您可以阅读有关 BuildKit 的功能here

例如,我克隆了上面的 qTox 存储库,因为它非常庞大。

--mount=cache 功能会自动创建用于缓存的临时目录,并将其挂载到容器内的 /tmp/git_cache/(目标)中。如果之前的一些图层发生了变化,例如echo A00 更改为 echo A01 则此克隆会立即完成,没有延迟,因为它只是从缓存中取出。

此外,根据您的要求,使用此缓存将使克隆存储库完全相同。只有当新提交出现在存储库中时,git pull 才会完成并且存储库更改。除非有新的提交,否则这个缓存的存储库将保持不变。因此,每次再次运行 docker build 时,您都会拥有相同的 git repo。

如果缓存目录长时间不使用或磁盘可用空间不足,Docker 很少会自动删除它。

正如您从上面的 docker-file 中看到的,最终的 git repo 将出现在容器的 /tmp/my_qtox/ 文件夹中。您可以将此路径更改为您的案例所需的任何内容。

您也可能已经注意到,我在安装 APT 包时使用了相同的缓存机制。这非常方便,因为在重建映像时,所有软件包都不会从远程 Ubuntu 服务器重新下载,而是从缓存目录中获取。当 apt install 之前的先前 docker 层发生更改或将新的 apt 包添加到安装列表时,这很有用,在这两种情况下,apt install 都会非常快地重新运行。

答案 1 :(得分:1)

不要使用git-clone(1),而是使用git-archive(1)(至少在最后)。它还包含已存档的修订,您可以在包含修订的文件中添加标记,例如创建一个标志文件。

对于需要完整克隆的存储库,请同时进行克隆(或将克隆后的元数据更改为基线)。

通常完全克隆应该不是特别必要的。如果,您还可以考虑在过程中使用 tar-pipe,在此过程中注意简化结果,以便缓存保持有效(仅在需要时失效)。