解决CI流水线中并发和构建结果可能互相覆盖的问题

71次阅读
没有评论

问题描述

使用gitlab-ci来生成一些仓库的Docker镜像,但他认为这个解决方案不够可靠。他担心多个构建在短时间内同时发生,导致构建编号较大的构建(例如构建 #100)会覆盖构建编号较小的构建(例如构建 #101)所产生的新的Docker镜像,特别是当作业不按顺序完成时(例如多个构建主机同时工作等)。

当前他希望使用的标签遵循以下模式:namespace/application:branch-name

问题的核心在于:

  1. 其他服务是如何解决这个问题的?(可能是每个分支按顺序运行构建吗?)
  2. 在gitlab环境中,如何以完全可靠的方式解决这个问题?

他理解,如果他使用提交的SHA来作为构建标签,这个问题将会消失。但出于以下原因,他希望继续使用分支名作为标签:

  • 废弃/旧的镜像会被Docker注册表自动清理
  • 分支名更方便使用

解决方案

方案1:使用构建编号添加标签

有一种常见的做法是将构建编号添加到标签中,这样可以保证每个构建都有唯一的标识。例如,标签可以被定义为:namespace/application:branch-name-buildNumber。这种方法可以确保不同构建的镜像拥有不同的标签,避免了覆盖问题。

在GitLab CI环境中,你可以使用预定义的变量 CI_JOB_ID 来获取当前作业的编号。你可以将这个编号添加到构建标签中,以确保唯一性。

示例:

build_image:
  stage: build
  script:
    - docker build -t "namespace/application:$CI_COMMIT_REF_NAME-$CI_JOB_ID" .

这将在构建标签中包含分支名和作业编号,以确保每个构建都有不同的标签。

方案2:定期清理不需要的镜像

为了避免存储过多无用的镜像,你可以定期清理那些不再需要的镜像。使用以下命令可以清理掉所有已经存在48小时以上的镜像:

docker image prune --all --filter until=48h

这个命令会清理掉所有已经存在超过48小时的镜像,不仅仅是悬空的镜像。通过定期执行这个命令,你可以确保只有最近的镜像被保留下来。

请注意,这个方法仅适用于清理Docker宿主机上的镜像,不会直接清理Docker注册表中的镜像。如果你需要清理注册表中的镜像,你可能需要查阅相关的Docker注册表清理方法。

总结

解决CI流水线中并发和构建结果可能互相覆盖的问题,你可以考虑使用构建编号来添加唯一的标签,以及定期清理不再需要的镜像。这样可以确保每个构建都有独特的标签,同时避免存储过多无用的镜像。记得根据你的实际情况和需求来选择适合的解决方案。

注意: 以上解决方案中的命令和方法可能会因版本差异而有所不同,请在执行之前做好备份,并根据实际情况进行适当的调整。

正文完