【问题标题】:How do i cache in gitlab ci while building docker images with docker:dind使用 docker:dind 构建 docker 映像时如何在 gitlab ci 中缓存
【发布时间】:2021-04-07 14:15:02
【问题描述】:

我有一个这样的gitlab-ci.yml

build and push docker image:
  stage: publish  
  variables:
    DOCKER_REGISTRY: amazon-registry
    AWS_DEFAULT_REGION: ap-south-1
    APP_NAME: sample-app
    DOCKER_HOST: tcp://docker:2375
  image: 
    name: amazon/aws-cli
    entrypoint: [""]
  services:
    - docker:dind 
  before_script:
    - amazon-linux-extras install docker
  script:
    - docker build -t $DOCKER_REGISTRY/$APP_NAME:master .
    - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
    - docker push $DOCKER_REGISTRY/$APP_NAME:master

此步骤需要 19=8 分钟才能完成,因为 docker 映像步骤未缓存。我希望能够缓存 before_script amazon-linux-extras install docker 以及我正在构建的 docker 映像。我们在自己的 gitlab 跑步者上运行。我已经搜索了答案,但找到了 4 年前的解决方案。有没有办法解决这个问题?另外,切换到docker:dind 会有帮助吗?

【问题讨论】:

    标签: docker caching gitlab-ci docker-in-docker


    【解决方案1】:

    我尝试过的一件事是在 docker build 中使用缓存层。
    您可以从您的注册表中提取现有图像,然后使用--cache-from 参数进行构建。

    job shell 是这样的:

      variables:
        IMAGE_TAG: $DOCKER_REGISTRY/$APP_NAME:master
      script:
        - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
        - docker pull $IMAGE_TAG || true
        - docker build --cache-from $IMAGE_TAG -t $IMAGE_TAG .
        - docker push $IMAGE_TAG
    

    gitlab-ci official document 中也提到了这个方法。

    【讨论】:

    • 谢谢卡尔,不知何故我没有意识到你必须先拉图像;)
    【解决方案2】:

    Gitlab CI 缓存不是这样工作的。例如,如果你有一个安装 npm 依赖项的作业,你可以缓存生成的 node_modules 目录,这样 npm install 就不需要再次运行,但它对安装系统包之类的事情没有帮助。

    关于docker:dind 服务,如果没有该服务,您将无法运行docker build...docker push ... 之类的命令,即使您将作业使用的图像切换为docker:latest。这有点违反直觉,但能够运行这些命令的唯一方法是使用 docker-in-docker 服务。

    但是,您并非不走运。我建议您将before_script 阶段中​​的步骤移动到您自己的扩展amazon/aws-cli 的docker 映像。只要您可以访问 docker hub、Gitlab 包含的注册表(如果使用 gitlab.com,它是可用的,否则管理员必须启用/配置它)、亚马逊的注册表(我认为是 ECR?)或私人运行的注册表,您可以创建您自己的自定义图像并在 Gitlab CI 管道中使用它们。

    这是一个 Dockerfile 示例:

    FROM amazon/aws-cli
    RUN amazon-linux-extras install docker
    

    这就是扩展现有amazon/aws-cli 映像并将before_script 安装移动到Docker 所需的全部内容。文件完成后,运行

    docker build /path/to/dockerfile-directory -t my_tag:latest
    

    之后,您需要登录到您的注册表docker login my.registry.example.com,然后推送图像docker push my_tag:latest。如果您不使用 Gitlab 的注册表或公共 docker hub,则需要配置您的作业或运行器(两者之一),以便他们可以通过您的注册表进行身份验证。你可以在这里阅读:https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#define-an-image-from-a-private-container-registry

    接下来,您只需在管道中使用它:

    build and push docker image:
      stage: publish  
      variables:
        DOCKER_REGISTRY: amazon-registry
        AWS_DEFAULT_REGION: ap-south-1
        APP_NAME: sample-app
        DOCKER_HOST: tcp://docker:2375
      image: 
        name: my_tag:latest
        entrypoint: [""]
      services:
        - docker:dind
      script:
        - docker build -t $DOCKER_REGISTRY/$APP_NAME:master .
        - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
        - docker push $DOCKER_REGISTRY/$APP_NAME:master
    

    您可以做的另一件事来节省管道时间(如果适用)是仅在您的 Dockerfile 发生更改时运行此步骤。这样,如果它没有但其他工作依赖它,他们可以重用创建的最后一个图像。您可以使用 rules 关键字和 changes 来做到这一点:

    build and push docker image:
      stage: publish  
      variables:
        DOCKER_REGISTRY: amazon-registry
        AWS_DEFAULT_REGION: ap-south-1
        APP_NAME: sample-app
        DOCKER_HOST: tcp://docker:2375
      image: 
        name: my_tag:latest
        entrypoint: [""]
      services:
        - docker:dind
      when: never
      rules:
        - changes:
          - Dockerfile
          when: always
      script:
        - docker build -t $DOCKER_REGISTRY/$APP_NAME:master .
        - aws ecr get-login-password | docker login --username AWS --password-stdin $DOCKER_REGISTRY
        - docker push $DOCKER_REGISTRY/$APP_NAME:master
    

    根级when: never 将作业的默认设置设置为从不运行,但rules 部分检查Dockerfile 是否有更改(如果需要,接受多个文件)。如果有更改,作业将始终运行。

    您可以在此处查看有关 rules 关键字的详细信息:https://docs.gitlab.com/ee/ci/yaml/#rules

    您可以在此处查看有关 Gitlab CI 的自定义 docker 映像的详细信息:https://docs.gitlab.com/ee/ci/docker/using_docker_images.html

    【讨论】:

      猜你喜欢
      • 2022-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      • 2021-12-29
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      相关资源
      最近更新 更多