Gitlab CI:如何避免在每次提交时重新构建镜像

3
我正在使用Gitlab CI来存储和部署docker镜像,但我遇到了一个大问题。每次提交代码,Gitlab CI 都会重新构建所有镜像。
第一步是构建我的通用镜像,需要大约 8 分钟的时间。目前我只修改子镜像,但每次提交后通用镜像仍然被重新构建。
因此,这个构建过程是浪费时间的,因为推送操作不会产生任何效果,因为镜像已经在 Gitlab 存储库中。
如何避免在Gitlab存储库中已经存在镜像时的镜像重构?
以下是gitlab-ci.yml文件。
build:
   tags:
       - docker_ci_build
   services:
       - docker:dind
   script:
       - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
       - >
           docker build 
           -t $CI_PROJECT/common:6.0.1 common

以下是一个Dockerfile:

FROM ubuntu:bionic
RUN apt-get update && \
     DEBIAN_FRONTEND=noninteractive \
     apt-get install -y packages && \
     apt-get clean && \
     rm -rf /var/lib/apt/lists/*
COPY file.conf /etc/common/

1
不看代表性的 .gitlab-ci.ymlDockerfile 文件,无法回答这个问题。 - Jonathon Reinhart
我编辑了第一篇帖子。但是我进行了新的搜索,似乎不可能实现。唯一的方法是在构建之前从您的注册表中拉取图像。但如果该图像尚不存在,则会导致构建失败。 - Vender Aeloth
1个回答

4

缓存似乎比我最初想的更加复杂,而各种拉取选项的docker文档未提及任何细微差别。

如果docker镜像可能存在或不存在,您实际上可以调整docker pull命令,即使拉取失败也可以通过您的构建:

- docker image pull $LATEST || true

如果存在,则会拉取$LATEST镜像,否则将继续进行构建。接下来的步骤是确保您的构建实际上可以使用它。
对于docker build,--pull选项似乎是您想要的,而且docker的文档说

--pull 始终尝试拉取图像的新版本

但实际上它似乎并没有对您正在构建的实际图像做任何事情。更有前途的是--cache-from,它允许您为docker可以从中缓存的图像命名。在我的简单测试中,我没有看到docker实际上使用我的缓存,可能是因为它没有足够的层次结构来利用缓存。
- docker image pull $LATEST_IMAGE || true
- docker build --pull -t $TAGGED_IMAGE --cache-from $LATEST_IMAGE .
- docker tag $TAGGED_IMAGE $LATEST_IMAGE
- docker push $LATEST_IMAGE
- docker push $TAGGED_IMAGE

如果你的构建镜像是多阶段构建,那么这可能会更有用,并且可以真正利用缓存。另外,你可以调整你的gitlab-ci脚本,以避免重复构建已存在的镜像。

如果需要构建和推送常见部分以及子项目时,你可能需要查看gitlab-ci流水线并创建可选阶段和触发器。

我在文件开头的variables部分中定义变量。最新版本的定义带有:latest标签,这基本上是项目的任何CI分支的最新构建。$TAGGED_IMAGE使用:$CI_COMMIT_SHORT_SHA定义,这将Docker镜像与git SHA进行标记,使得在开发环境中进行Kubernetes部署更加容易跟踪。


"docker build --pull" 不起作用。每次提交都会得到完整的构建,而没有任何更改。 - Vender Aeloth
作为 GitLab 的一部分,您是否正在从私有 Docker 注册表中推送和拉取?我不记得在 GitLab 的 CI 变量列表(https://docs.gitlab.com/ee/ci/variables/)中看到 $CI_PROJECT 被定义。 - Nick
我在GitLab Registry中进行推送/拉取操作,CI_PROJECT是我的gitlab_ci.yml开头的自定义变量,等于CI_PROJECT_URL去掉https://。 - Vender Aeloth
我添加了更多信息,你可以尝试使用 docker image pull $NAME || true。你的构建实际上是否利用了镜像缓存,还是只在不存在镜像时才构建镜像? - Nick
1
是的,它有效。|| 如果图像不存在,则true允许继续作业。在构建命令中,--cache-from是强制性的。谢谢。 - Vender Aeloth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接