13

在文件中gitlab-ci有一个选项可以在.gitlab-ci.yml任何实际脚本运行之前执行命令,称为before_script. .gitlab-ci.yml示例说明在此处安装辅助程序。但是,我注意到的是,当使用 docker 执行器时,这些更改不会缓存在 Docker 中。我天真地假设在运行这些命令之后,docker 会缓存图像,因此在下一次运行或测试时,docker 只会加载before_script. 这将大大加快构建速度。

例如,我的.gitlab-ci.yml看起来有点像:

image: ubuntu

before_script:
    - apt-get update -qq && apt-get install -yqq make ...

build:
    script:
        - cd project && make

一个可能的解决方案是转到运行器机器并创建一个 docker 映像,该映像可以构建我的软件而无需任何其他安装,然后image在 yaml 文件的部分中引用它。这样做的缺点是,每当我想添加依赖项时,我都需要登录到运行器机器并在构建成功之前更新映像。如果我只需将依赖项添加到末尾apt-get install并让 docker / gitlab-ci 处理适当的缓存,那就更好了。

中还有一个cache命令.gitlab-ci.yml,我尝试将其设置为untracked: true,我认为它会缓存不是我项目副产品的所有内容,但它似乎没有任何效果。

有没有办法得到我想要的行为?

4

2 回答 2

10

您可以添加一个阶段来首先构建图像。如果图像没有任何变化,这个阶段会很短,不到 1 秒。

您可以在以下阶段使用该图像,加快整个过程。

这是一个示例.gitlab-ci.yml

stages:
  - build_test_image
  - test

build_test:
  stage: build_test_image
  script:
    - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:test -f dockerfiles/test/Dockerfile .
    - docker push $CI_REGISTRY_IMAGE:test
  tags:
    - docker_build

test_syntax:
  image: $CI_REGISTRY_IMAGE:test
  stage: test
  script:
    - pip install flake8
    - flake8 --ignore=E501,E265 app/

看标签docker_build。该标签用于强制在具有该标签的运行器上执行阶段。该运行器的执行器是shell,它仅用于构建 Docker 映像。所以,runner 所在的主机应该已经安装了 Docker Engine。我发现这个解决方案比 docker in docker 和其他解决方案更适合我的需求。

此外,我使用的是私有注册表,这就是我使用$CI_REGISTRY*变量的原因,但您可以使用 DockerHub 而无需指定注册表。不过,问题在于在 DockerHub 上进行身份验证。

于 2016-12-14T16:16:54.957 回答
2

我处理这个问题的方式是,我在 Docker Hub 上为我们的每个项目都有自定义图像,并从.gitlab-ci.yml. 如果我需要新的依赖项,我会编辑用于创建初始映像的 Dockerfile,重新构建映像,并使用特定标签对其进行标记,然后推送到 Docker Hub。

cat "RUN apt-get install gcc" >> Dockerfile
ID=$(docker build)
docker tag $ID ACCOUNT/gitlab_ci_image:gcc
docker push ACCOUNT/gitlab_ci_image

然后我更新.gitlab-ci.yml文件以指向该特定版本的图像。

image: ACCOUNT/gitlab_ci_image:gcc

build:
    script:
        - cd project && make

这允许我根据我尝试测试的提交具有不同的依赖关系(因为该gitlab-ci.yml提交中的文件告诉运行者使用哪个)。它还避免了每次在特定运行器上运行测试时都需要安装依赖项,因为运行器将重复使用相同的图像,只要它不改变。

另一个好处是,对于托管在 Docker Hub 上的图像,如果运行器需要一个本地没有的特定标签,它会自动获取正确的标签,这样你就可以拥有 10 个运行器并且只维护一个图像这种维护可以在您自己的工作站或任何机器上完成。

我个人认为这是一个比尝试在跑步者的图像中缓存任何东西更好的解决方案。当您创建新分支以在较新版本的依赖项上测试代码时尤其如此。如果你有缓存,你的稳定分支和开发分支会有不同的测试环境问题。同样在我看来,测试应该在尽可能干净的环境中运行,而这个设置可以实现这一点。

于 2016-01-15T22:19:00.253 回答