Share feedback
Answers are generated based on the documentation.

Azure Pipelines 与 Docker 入门

本文档为社区贡献。Docker 感谢 Kristiyan Velkov 的宝贵贡献。

前置条件

开始之前,请确保满足以下要求:

概述

本指南将带你使用 Azure Pipelines 构建和推送 Docker 镜像,为容器化应用实现流畅且安全的 CI 工作流。你将学会:

  • 安全配置 Docker 认证。
  • 设置自动化流水线以构建和推送镜像。

配置 Azure DevOps 与 Docker Hub 集成

步骤 1:配置 Docker Hub 服务连接

为在 Azure Pipelines 中安全地认证 Docker Hub:

  1. 在 Azure DevOps 项目中导航至 Project Settings > Service Connections
  2. 选择 New service connection > Docker Registry
  3. 选择 Docker Hub,并提供你的 Docker Hub 凭据或访问令牌。
  4. 为服务连接起一个易识别的名称,例如 my-docker-registry
  5. 仅授予需要的特定流水线访问权限,以提升安全性并遵循最小权限原则。
Important

除非绝对必要,否则避免选择授予所有流水线访问权限的选项。始终应用最小权限原则。

步骤 2:创建流水线

在仓库根目录添加以下 azure-pipelines.yml 文件:

# 在提交到 main 分支时触发流水线
trigger:
  - main

# 在针对 main 分支的拉取请求时触发流水线
pr:
  - main

# 定义变量以便在流水线中复用
variables:
  imageName: 'docker.io/$(dockerUsername)/my-image'
  buildTag: '$(Build.BuildId)'
  latestTag: 'latest'

stages:
  - stage: BuildAndPush
    displayName: Build and Push Docker Image
    jobs:
      - job: DockerJob
        displayName: Build and Push
        pool:
          vmImage: ubuntu-latest
          demands:
            - docker
        steps:
          - checkout: self
            displayName: Checkout Code

          - task: Docker@2
            displayName: Docker Login
            inputs:
              command: login
              containerRegistry: 'my-docker-registry'  # Service connection name

          - task: Docker@2
            displayName: Build Docker Image
            inputs:
              command: build
              repository: $(imageName)
              tags: |
                $(buildTag)
                $(latestTag)
              dockerfile: './Dockerfile'
              arguments: |
                --sbom=true
                --attest type=provenance
                --cache-from $(imageName):latest
            env:
              DOCKER_BUILDKIT: 1

          - task: Docker@2
            displayName: Push Docker Image
            condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
            inputs:
              command: push
              repository: $(imageName)
              tags: |
                $(buildTag)
                $(latestTag)

          # 可选:仅用于自托管代理的登出
          - script: docker logout
            displayName: Docker Logout (Self-hosted only)
            condition: ne(variables['Agent.OS'], 'Windows_NT')

此流水线的作用

此流水线自动化了 main 分支的 Docker 镜像构建和部署流程。它通过缓存、标签和条件清理等最佳实践,确保安全高效的流水线工作流。具体功能如下:

  • 在向 main 分支提交和拉取请求时自动触发。
  • 使用 Azure DevOps 服务连接安全认证 Docker Hub。
  • 使用 Docker BuildKit 构建和标记镜像,实现缓存优化。
  • 推送 buildId 和 latest 两个标签到 Docker Hub。
  • 如果在自托管 Linux 代理上运行,则登出 Docker。

流水线工作原理

步骤 1:定义流水线触发器

trigger:
  - main

pr:
  - main

此流水线在以下情况自动触发:

  • 推送到 main 分支的提交
  • 针对 main 分支的拉取请求
Tip

步骤 2:定义通用变量

variables:
  imageName: 'docker.io/$(dockerUsername)/my-image'
  buildTag: '$(Build.BuildId)'
  latestTag: 'latest'

这些变量确保流水线各步骤中命名、版本和复用的一致性:

  • imageName:Docker Hub 上的镜像路径
  • buildTag:每次流水线运行的唯一标签
  • latestTag:最新镜像的稳定别名
Important

变量 dockerUsername 不会自动设置。
请在 Azure DevOps 流水线变量中安全设置:

  1. 进入 Pipelines > Edit > Variables
  2. 添加 dockerUsername,值为你的 Docker Hub 用户名

了解更多信息:在 Azure Pipelines 中定义和使用变量

步骤 3:定义流水线阶段和作业

stages:
  - stage: BuildAndPush
    displayName: Build and Push Docker Image

此阶段仅在源分支为 main 时执行。

Tip

了解更多信息:Azure Pipelines 中的阶段条件

步骤 4:作业配置

jobs:
  - job: DockerJob
  displayName: Build and Push
  pool:
    vmImage: ubuntu-latest
    demands:
      - docker

此作业使用 Microsoft 托管代理提供的最新 Ubuntu 虚拟机镜像(支持 Docker)。如有需要,可替换为自定义池以使用自托管代理。

Tip

了解更多信息:在流水线中指定池

步骤 4.1:检出代码

steps:
  - checkout: self
    displayName: Checkout Code

此步骤将仓库代码拉取到构建代理中,以便流水线能够访问 Dockerfile 和应用文件。

Tip

了解更多信息:checkout 步骤文档

步骤 4.2:认证 Docker Hub

- task: Docker@2
  displayName: Docker Login
  inputs:
    command: login
    containerRegistry: 'my-docker-registry'  # Replace with your service connection name

使用预配置的 Azure DevOps Docker 注册表服务连接进行安全认证,避免直接暴露凭据。

Tip

了解更多信息:Docker Hub 的服务连接使用

步骤 4.3:构建 Docker 镜像

 - task: Docker@2
    displayName: Build Docker Image
    inputs:
      command: build
      repository: $(imageName)
      tags: |
          $(buildTag)
          $(latestTag)
      dockerfile: './Dockerfile'
      arguments: |
          --sbom=true
          --attest type=provenance
          --cache-from $(imageName):latest
    env:
      DOCKER_BUILDKIT: 1

此步骤构建镜像时包含:

  • 两个标签:一个带唯一构建 ID,一个为 latest
  • 启用 Docker BuildKit 以实现更快构建和高效层缓存
  • 从最近推送的 latest 镜像拉取缓存
  • 软件物料清单 (SBOM) 以提升供应链透明度
  • 证明声明以验证镜像的构建方式和位置
Tip

步骤 4.4:推送 Docker 镜像

- task: Docker@2
  displayName: Push Docker Image
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
  inputs:
      command: push
      repository: $(imageName)
      tags: |
        $(buildTag)
        $(latestTag)

通过应用此条件,流水线在每次运行时都会构建 Docker 镜像以确保早期发现问题,但仅在更改合并到主分支时才将镜像推送到注册表——保持 Docker Hub 的整洁和专注。

这会将两个标签上传到 Docker Hub:

  • $(buildTag) 确保每次运行的可追溯性。
  • latest 用于最新镜像引用。

步骤 4.5:登出 Docker(自托管代理)

- script: docker logout
  displayName: Docker Logout (Self-hosted only)
  condition: ne(variables['Agent.OS'], 'Windows_NT')

在基于 Linux 的自托管代理上,流水线结束时执行 docker logout 以主动清理凭据,增强安全态势。

总结

通过此 Azure Pipelines CI 设置,你可以获得:

  • 使用内置服务连接进行安全的 Docker 认证。
  • 由代码变更触发的自动化镜像构建和标记。
  • 利用 Docker BuildKit 缓存的高效构建。
  • 在持久化代理上通过登出实现安全清理。
  • 满足现代软件供应链要求的构建镜像,包含 SBOM 和证明声明。

了解更多信息