14

我正在运行以下 yaml 脚本来构建 docker 映像并推送到 kubernetes 集群,但同时我想在构建 yaml 脚本时在 azure DevOps 中启用 docker 层缓存。请您解释一下如何启用或如何添加azure devops 中的任务来执行此操作。

yaml:

# Starter pipeline
# Start with a minimal pipeline that you can customize to build and deploy your code.
# Add steps that build, run tests, deploy, and more:
# https://aka.ms/yaml

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

variables:
  tag: 'web'
  DockerImageName: 'boiyaa/google-cloud-sdk-nodejs'


steps:
- task: Docker@2
  inputs:
    command: 'build'
    Dockerfile: '**/Dockerfile'
    tags: 'web'
  
- script: |
    echo ${GCLOUD_SERVICE_KEY_STAGING} > ${HOME}/gcp-key.json
               gcloud auth activate-service-account --key-file ${HOME}/gcp-key.json --project ${GCLOUD_PROJECT_ID_STAGING}
               gcloud container clusters get-credentials ${GCLOUD_PROJECT_CLUSTER_ID_STAGING} \
        --zone ${GCLOUD_PROJECT_CLUSTER_ZONE_STAGING} \
        --project ${GCLOUD_PROJECT_ID_STAGING}
  displayName: 'Setup-staging_credentials'


- bash: bash ./deploy/deploy-all.sh staging
  displayName: 'Deploy_script_staging'
4

5 回答 5

33

这是我解决这个问题的方法。我只是将最新版本的映像从我的注册表(在我的例子中为 Azure 容器注册表)拉到 Azure DevOps 托管代理。然后我添加--cache-from到 Docker 构建参数,指向它刚刚下载到本地机器/缓存的最新标签。

- task: Docker@2
  inputs:
    containerRegistry: '$(ContainerRegistryName)'
    command: 'login'

- script: "docker pull $(ACR_ADDRESS)/$(REPOSITORY):latest"
  displayName: Pull latest for layer caching
  continueOnError: true # for first build, no cache

- task: Docker@2
  displayName: build
  inputs:
    containerRegistry: '$(ContainerRegistryName)'
    repository: '$(REPOSITORY)'
    command: 'build'
    Dockerfile: './dockerfile '
    buildContext: '$(BUILDCONTEXT)'
    arguments: '--cache-from=$(ACR_ADDRESS)/$(REPOSITORY):latest' 
    tags: |
      $(Build.BuildNumber)
      latest

- task: Docker@2
  displayName: "push"
  inputs:
    command: push
    containerRegistry: "$(ContainerRegistryName)"
    repository: $(REPOSITORY) 
    tags: |
      $(Build.BuildNumber)
      latest
于 2020-07-23T19:42:21.083 回答
12

Azure DevOps 目前不支持 Docker 层缓存。原因如下:

在 Microsoft 托管代理的当前设计中,每个作业都被分派到新配置的虚拟机上。这些虚拟机在作业完成后被清理,不会持久化,因此不能重复用于后续作业。虚拟机的短暂性阻止了缓存 Docker 层的重用。

然而:

  1. 使用自托管代理可以进行 Docker 层缓存。您可以尝试创建本地代理来运行构建管道。

    您可能需要禁用作业的选项“允许脚本访问 OAuth 令牌”。因为 $(System.AccessToken) 是使用 --build-arg ACCESS_TOKEN=$(System.AccessToken) 传递给 docker build 的,它的值在每次运行时都会变化,这会使缓存失效。

  2. 您还可以使用缓存任务docker save/load命令将保存的 Docker 层上传到 Azure DevOps 服务器并在未来运行时将其还原。检查此线程以获取更多信息。

  3. 本博客中描述的另一个解决方法是在Dockerfile中使用--cache-from 和 --target

如果上述变通办法不令人满意,您可以向Microsoft 开发团队提交功能请求。单击Suggest a Feature并选择Azure DevOps

于 2019-12-11T03:54:50.337 回答
8

编辑:正如评论中所指出的,这个功能实际上在没有 BuildKit的情况下可用。这里有一个关于如何在构建过程中使用 Docker 镜像作为缓存源的示例。

通过将变量DOCKER_BUILDKIT: 1(请参阅此链接)添加到管道作业并安装buildx,我设法通过将缓存存储为单独的图像来实现层缓存。有关一些基础知识,请参阅此链接

这是 Azure DevOps 中的示例步骤

- script: |
    image="myreg.azurecr.io/myimage"
    tag=$(Build.SourceBranchName)-$(Build.SourceVersion)
    cache_tag=cache-$(Build.SourceBranchName)

    docker buildx create --use
    docker buildx build \
      -t "${image}:${tag}"
      --cache-from=type=registry,ref=${image}:${cache_tag}\
      --cache-to=type=registry,ref=${image}:${cache_tag},mode=max \
      --push \
      --progress=plain \
      .
  displayName: Build & push image using remote BuildKit layer cache

这当然需要每次运行都下载图像缓存,但是对于在 Docker 构建过程中具有长时间运行安装步骤的图像,这肯定会更快(在我们的例子中从大约 8 分钟到 2 分钟)。

于 2020-02-18T21:56:16.123 回答
2

看起来微软不久前为 Azure Devops 引入了管道缓存,并且可以缓存 docker 层。请参阅此链接。

于 2021-05-17T19:44:24.973 回答
0

如果您不想将缓存推送到容器注册表,还可以在 Pipeline VM 中设置“本地”Docker 层缓存。您将需要以下步骤:

- task: Docker@2
  displayName: Login to ACR
  inputs:
    command: login
    containerRegistry: $(SERVICE_NAME)
- task: Cache@2
  displayName: Cache task
  inputs:
    key: 'docker | "$(Agent.OS)" | "$(Build.SourceVersion)"'
    path: /tmp/.buildx-cache
    restoreKeys: 'docker | "$(Agent.OS)"'

- bash: |
    docker buildx create --driver docker-container --use
    docker buildx build --cache-to type=local,dest=/tmp/.buildx-cache-new --cache-from type=local,src=/tmp/.buildx-cache --push --target cloud --tag $REGISTRY_NAME/$IMAGE_NAME:$TAG_NAME .
  displayName: Build Docker image

# optional: set up deploy steps here

- task: Docker@2
  displayName: Logout of ACR
  inputs:
    command: logout
    containerRegistry: $(SERVICE_NAME)

这里的关键是设置 Docker并使用and标志buildx运行它,而不是使用 Azure Docker 任务。您还需要使用该任务确保在后续管道运行中重新加载 Docker 缓存,并且您必须设置手动交换步骤,其中新生成的缓存替换旧缓存。--cache-to--cache-fromCache

于 2021-09-15T18:34:46.583 回答