如何在 Azure DevOps 中启用 Docker 层缓存
How to Enable Docker layer caching in Azure DevOps
我是 运行 下面的 yaml 脚本,用于构建 docker 图像并推送到 kubernetes 集群,但同时我想在 azure DevOps 中启用 docker 层缓存,同时构建 yaml script.Could 请解释如何启用或如何在 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'
Docker 层缓存目前在 Azure DevOps 中不受支持。 reason表示如下:
In the current design of Microsoft-hosted agents, every job is dispatched to a newly provisioned virtual machine. These virtual machines are cleaned up after the job reaches completion, not persisted and thus not reusable for subsequent jobs. The ephemeral nature of virtual machines prevents the reuse of cached Docker layers.
但是:
Docker 层缓存可以使用自托管代理。您可以尝试 creating your on-premise agents 到 运行 您的构建管道。
您可能需要禁用作业的选项“允许脚本访问 OAuth 令牌”。因为 $(System.AccessToken) 使用 --build-arg ACCESS_TOKEN=$(System.AccessToken) 传递给 docker 构建,并且它的值因每个 运行, 这将使缓存失效。
您也可以使用 Cache task and docker save/load
commands to upload the saved Docker layer to Azure DevOps server and restore it on the future run. Check this thread 获取更多信息。
此 blog 中描述的另一种解决方法是在 Docker 中使用 --cache-from 和 --target文件。
如果上述变通办法不令人满意,您可以向 Microsoft Develop Team 提交 feature request。单击建议功能 并选择Azure DevOps。
编辑:正如评论中所指出的,此功能实际上可用 没有 BuildKit。有一个示例 here 关于如何在构建期间使用 Docker 图像作为缓存源。
通过添加变量 DOCKER_BUILDKIT: 1
(参见 this link) to the pipeline job and installing buildx
, I managed to achieve layer caching by storing the cache as a separate image. See this link for some basics
这是 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)。
这是我解决这个问题的方法。我只是将最新版本的映像从我的注册表(在我的例子中是 Azure 容器注册表)拉到 Azure DevOps 托管代理。然后我将 --cache-from
添加到 Docker 构建参数,指向它刚刚下载到本地 machine/cache.
的最新标签
- 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
看起来 Microsoft 不久前为 Azure Devops 引入了管道缓存,并且可以缓存 docker 层。 See this link.
如果您不想将缓存推送到容器注册表,您还可以在管道 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)
这里的关键是使用 --cache-to
和 --cache-from
标志设置 Docker buildx
和 运行 而不是使用 Azure Docker 任务。您还需要使用 Cache
任务来确保 Docker 缓存在后续管道 运行 中重新加载,并且您必须设置一个手动交换步骤,其中新生成的缓存替换旧缓存。
我是 运行 下面的 yaml 脚本,用于构建 docker 图像并推送到 kubernetes 集群,但同时我想在 azure DevOps 中启用 docker 层缓存,同时构建 yaml script.Could 请解释如何启用或如何在 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'
Docker 层缓存目前在 Azure DevOps 中不受支持。 reason表示如下:
In the current design of Microsoft-hosted agents, every job is dispatched to a newly provisioned virtual machine. These virtual machines are cleaned up after the job reaches completion, not persisted and thus not reusable for subsequent jobs. The ephemeral nature of virtual machines prevents the reuse of cached Docker layers.
但是:
Docker 层缓存可以使用自托管代理。您可以尝试 creating your on-premise agents 到 运行 您的构建管道。
您可能需要禁用作业的选项“允许脚本访问 OAuth 令牌”。因为 $(System.AccessToken) 使用 --build-arg ACCESS_TOKEN=$(System.AccessToken) 传递给 docker 构建,并且它的值因每个 运行, 这将使缓存失效。
您也可以使用 Cache task and
docker save/load
commands to upload the saved Docker layer to Azure DevOps server and restore it on the future run. Check this thread 获取更多信息。此 blog 中描述的另一种解决方法是在 Docker 中使用 --cache-from 和 --target文件。
如果上述变通办法不令人满意,您可以向 Microsoft Develop Team 提交 feature request。单击建议功能 并选择Azure DevOps。
编辑:正如评论中所指出的,此功能实际上可用 没有 BuildKit。有一个示例 here 关于如何在构建期间使用 Docker 图像作为缓存源。
通过添加变量 DOCKER_BUILDKIT: 1
(参见 this link) to the pipeline job and installing buildx
, I managed to achieve layer caching by storing the cache as a separate image. See this link for some basics
这是 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)。
这是我解决这个问题的方法。我只是将最新版本的映像从我的注册表(在我的例子中是 Azure 容器注册表)拉到 Azure DevOps 托管代理。然后我将 --cache-from
添加到 Docker 构建参数,指向它刚刚下载到本地 machine/cache.
- 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
看起来 Microsoft 不久前为 Azure Devops 引入了管道缓存,并且可以缓存 docker 层。 See this link.
如果您不想将缓存推送到容器注册表,您还可以在管道 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)
这里的关键是使用 --cache-to
和 --cache-from
标志设置 Docker buildx
和 运行 而不是使用 Azure Docker 任务。您还需要使用 Cache
任务来确保 Docker 缓存在后续管道 运行 中重新加载,并且您必须设置一个手动交换步骤,其中新生成的缓存替换旧缓存。