GitLab CI/CD:带有 Git 的 Docker 镜像

4

我有以下的gitlab-ci.yaml

image: docker:19.03.13

variables:
  DOCKER_TLS_CERTDIR: "/certs"

services:
  - docker:19.03.13-dind

build-django_and_fastapi:
  before_script:
    - echo "$DOCKER_REGISTRY_PASS" | docker login $DOCKER_REGISTRY --username $DOCKER_REGISTRY_USER --password-stdin
  stage: build
  script:
    - mkdir test
    - cd test
    - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/xxxx/yyyy.git
    - cd ..
    - docker build ./test

我得到了 /bin/sh: eval: line xxx: git: not found

如何将git包添加到docker:19.03.13镜像中


为什么你需要另一个项目?它对于构建有什么重要性?为什么你只在该目录内构建?现在没有明确的原因说明为什么你需要使用 Git 以及这个其他项目。 - Simon Schrottner
无论是什么,我想要克隆一些东西并进行操作。为此我需要使用Git。 - Santhosh
很抱歉这么不合适,但你使用的技术存在明显的误解,而且达成目标总有其他途径。你试图强行走自己的路,而不是让别人帮助你引导你通过更安全、更简单的通道。我可以向你解释如何创建一个带有 Git 的 Docker 镜像,以供你在工作中使用。但也许那并不是你所需要的,反而会让你的生活变得更加复杂。也许你需要的只是多个 Docker 镜像,你可以从中依赖,或者你可能误解了 GitLab CI 的基本原理。我只是想帮助你。 - Simon Schrottner
我有两个GitLab仓库。现在我正在从它们两个创建单个Docker镜像。我创建了一个只包含Dockerfile的第三个仓库(它会复制克隆的仓库),我将手动触发流水线。 - Santhosh
你看,有很多不同的选项来解决这个问题,在我看来,有一些更容易处理。我希望我的贡献对你有所帮助,并给你指引。 - Simon Schrottner
2个回答

2
总结评论:目标是将两个其他存储库的内容构建为Docker镜像。因此,我们希望在同一构建阶段同时使用git和docker,或者至少尝试这样做。我提供了不同的选项,可以用来实现这一目标。
选项1:将提取逻辑迁移到Dockerfile中
与其在构建镜像上胡闹,我更愿意将此逻辑迁移到我的Dockerfile中。通常情况下,我有更容易处理此类事情的方法,在Dockerfile中添加一个层以进行git和删除操作比尝试在包含docker和git的构建镜像中更快。
但这取决于您的Dockerfile和您正在使用的Docker基本图像,使用debian/alpine等系统很容易实现,它们有自己的软件包管理器。
选项2:构建包含docker和git的Docker镜像
我最不喜欢的是这种选择。始终存在正确设置docker或另外安装git的问题。但我也会在这里概述该过程。
在这种情况下,您需要拥有自己的Docker镜像,其中您要么:
  • 选择Docker镜像并安装Git
  • 选择Git镜像并安装Docker
  • 从头开始构建一个全新的镜像
  • (您可以尝试找出使用的软件包管理器,并在脚本块中安装它)

但这增加了复杂性,比执行Option 1.更费力,而且提供的安全性较Option 3.较低。

Option 3: 使用API而非GIT(我推荐的方式)

不使用git来获取内容,还有API https://docs.gitlab.com/ee/api/repositories.html#get-file-archive

它允许您将特殊的ref下载为zip/tar等格式,比git checkout更易于使用。这也可以与Option 1.结合使用,因为它允许通过curl轻松获取内容。

这个选项的好处是,不会加载git历史记录,只会加载当前状态。这可能会改善构建时间。

Option 4: 多个构建步骤

不要试图合并docker构建和git checkout,可以将两者分成两个作业。第一个作业使用git提取仓库,第二个作业用于docker构建。

这里需要注意的重点是artifacts指令,您可以使用它来定义在下一阶段/构建中可用的文件。可以查看https://docs.gitlab.com/ee/ci/yaml/#artifacts,该资源对该指令非常有用。

选项5:使用git子模块

可以将其他存储库作为git子模块添加,而不是手动进行checkout。子模块可以视为指向其他git存储库的子目录。附带了特殊的checkout行为,但是通过更仔细地查看子模块,您应该可以很容易地解决此问题。

请注意设置GIT_SUBMODULE_STRATEGY,以便获取它们。 https://docs.gitlab.com/ee/ci/runners/configure_runners.html#git-submodule-strategy


我忘记了一个选项,我会添加它 - 添加了多个步骤和工件指令。 - Simon Schrottner
值得注意的是,还可以使用git子模块的可能性 - 我会添加它。 - Simon Schrottner
对于选项2,有一个预装git的官方Docker镜像:docker:git。 - Kipr

1

我必须在 Docker 镜像中安装 Git

image: docker:19.03.13

variables:
  DOCKER_TLS_CERTDIR: "/certs"

services:
  - docker:19.03.13-dind

build-django_and_fastapi:
  stage: build
  script:
    - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.gitlab.com
    - apk update
    - apk add git
    - mkdir test
    - cd test
    - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/xxxx/yyyy.git
    - cd ..
    - docker build ./test

因此,在脚本中我已经添加了apk add git

关于从多个仓库的源代码创建镜像的方法

我更喜欢为DockerFile准备完整的上下文文件夹,然后进行构建。

所以在脚本中我这样做

script
  - make folders for src codes
  - clone the src codes into those folders
  - build the image using docker build

我这样做的原因是,我们可以在构建镜像时利用缓存。所以如果前面的10个步骤都成功了,下一次构建镜像时就会使用缓存的层,并从第11个步骤开始。
因为构建镜像需要对 Dockerfile 进行一些编辑,直到我们得到正确的镜像。因此,层的缓存非常有帮助。
如果我尝试在 Dockerfile 中进行 git 克隆,可能无法利用缓存。
当然,在本地电脑上我可以使用缓存机制,但在 GitLab Docker 中我不确定如何使用它。

请考虑将所有仓库的.git添加到.dockerignore文件中 - 如果您不需要在Docker镜像中包含Git历史记录。 - Simon Schrottner
1
请查看 https://blog.callr.tech/building-docker-images-with-gitlab-ci-best-practices/ 了解如何提前加载现有镜像以及构建 Docker 镜像的其他最佳实践。 - Simon Schrottner

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