镜像构建并且推送到镜像仓库

通过流水线的内置镜像构建任务模板,可以实现镜像的构建并自动推送到ACR镜像仓库。流水线执行环境分为默认执行环境和专有执行环境两种模式。本文分别介绍如何在默认执行环境下和专有执行环境下构建镜像,以及如何使用镜像构建和部署进行完整的CI/CD流程。

默认构建环境使用限制

  • 磁盘空间不超过10 GB。

  • 构建任务超时最大不能超过15分钟。

  • GitHub代码源使用海外新加坡地域,GitLab或Codeup使用中国杭州地域。

  • 不支持固定IP地址以及网段,不支持IP白名单方式访问其他网站。

如果默认构建环境不满足您的需求,您可以使用专有执行环境构建镜像。具体信息,请参见使用专有执行环境构建镜像

前提条件

  • 如果您使用的是私有ACR镜像仓库,需要为角色AliyunFCServerlessDevsRole授予ACR的写权限,例如AliyunContainerRegistryFullAccess或者自定义权限策略。具体操作,请参见授予RAM用户自定义策略

  • 如果您使用的是ACR企业版镜像仓库,需要使用流水线专有执行环境在指定VPC内执行流水线构建任务。具体操作,请参见使用专有执行环境构建镜像

  • 如果您使用镜像构建任务,需要将资源描述文件s.yaml中的component: fc build --use-docker钩子删除,以保证部署阶段不执行镜像构建。

使用默认执行环境构建镜像

您可以通过函数计算控制台,找到应用,在流水线管理页签的流水线详情区域,选择镜像构建任务模板,使用任务模板更新右侧流水线YAML。操作流程为任务模板(下图中①)->构建(下图中②)->镜像构建(下图中③)->更新右侧YAML文件(下图中④)。

image.png

完整的镜像构建流水线YAML示例如下。

kind: Pipeline
name: "image-build-pipeline"
description: 'demo pipeline'
labels:
  myLabel: image-build
spec:
  templateSpec:
    tasks:
      - name: build-push
        context:
          data:
            # 任务显示名字,用于在控制台中展示。
            displayName: 镜像构建
            # 打开任务执行,默认关闭。
            enable: true
            # 指定构建信息。
            build: 
              # 指定dockerfile,使用代码仓库中的相对路径。不指定时默认为./Dockerfile。
              dockerfile: code/Dockerfile
              # 指定镜像名,必须是ACR镜像。
              image: registry-vpc.cn-hangzhou.aliyuncs.com/pipeline-demo/demo-repo:latest
              # 指定构建上下文目录。不指定时默认使用Dockerfile所在目录。
              context: ./context
        # 任务模板指定为内置的模板build-image-task。
        taskTemplate: build-image-task
        runAfters: []

使用专有执行环境构建镜像

如果默认执行环境无法满足需求,您可以使用流水线专有执行环境,让流水线任务在您自己的账号下运行。使用专有执行环境,可以自定义流水线任务的地域、网络、资源规格、超时等配置。关于流水线专有执行环境的介绍,请参见流水线执行环境

您可以通过图形化或者YAML编辑的方式来配置流水线执行环境。

重要

专有执行环境会让构建任务在您自己账号的函数计算下执行,因此会产生相关费用。具体操作,请参见计费概述

使用NAS进行缓存来构建镜像

如果您的Dockerfile中基础镜像很大,例如,使用了一些模型或者CUDA执行环境,每次构建都拉取基础镜像会影响构建速度并且还可能导致磁盘空间不足问题,此时您可以使用NAS来缓存基础镜像解决以上问题。

流程介绍

  1. 使用流水线专有执行环境并且绑定VPC以及NAS。

  2. 使用镜像预热将基础镜像缓存到NAS中。

  3. 使用NAS中的缓存来构建镜像。

YAML示例

kind: Pipeline
name: "image-build-use-cache-pipeline"
description: 'demo pipeline'
labels:
  myLabel: image-build-use-cache
spec:
  templateSpec:
    context:
      data:
        # 指定专有执行环境。
        runnerConfig:
          regionId: cn-hangzhou
          logConfig:
            project: demo-project
            logstore: demo-logstore
          # 网络配置,和NAS所在VPC保持一致。
          vpcConfig:
            securityGroupId: sg-xxxx
            vSwitchIds:
              - vsw-xxx
            vpcId: vpc-xxxx
          # NAS配置。
          nasConfig:
            groupId: 0
            userId: 0
            mountPoints:
              - enableTLS: false
                # 缓存使用的本地目录。
                mountDir: /mnt/image-cache
                # 缓存存放的远端目录。
                serverAddr: xxxx.cn-hangzhou.nas.aliyuncs.com:/image-cache
          # 实例规格建议8核32G,磁盘10GB。
          cpu: 8
          memory: 32768
          diskSize: 10240
          # 构建超时时间。
          timeout: 1800
    tasks:
      - name: build-push
        context:
          data:
            # 任务显示名字,用于在控制台中展示。
            displayName: 镜像构建
            # 打开任务执行,默认关闭
            enable: true
            # 将基础镜像预热到缓存。
            warm: 
              # 需要预热的基础镜像,可以指定多个。
              images:
              - registry-vpc.cn-hangzhou.aliyuncs.com/pipeline-demo/base-image-1:debug
              - registry-vpc.cn-hangzhou.aliyuncs.com/pipeline-demo/base-image-2:debug
              # 基础镜像要缓存的路径。
              cacheDir: "/mnt/image-cache" 
            # 指定构建信息。
            build: 
              # 指定dockerfile,使用代码仓库中的相对路径。不指定时默认为./Dockerfile。
              dockerfile: code/Dockerfile
              # 指定镜像名,必须是ACR镜像。
              image: registry-vpc.cn-hangzhou.aliyuncs.com/pipeline***/demo***:latest
              # 使用基础镜像的缓存路径。
              cacheDir: "/mnt/image-cache" 
        # 任务模板指定为内置的模板build-image-task。
        taskTemplate: build-image-task
        runAfters: []

使用缓存后,如果命中缓存,会打印Found manifest at ...的信息。

image.png

您也可以将构建和缓存预热任务拆分,单独进行预热以及构建。YAML示例如下。

- name: only-warm
  context:
    data:
      enable: true
      # 将基础镜像预热到缓存。
      warm: 
        # 需要预热的基础镜像,可以指定多个。
        images:
        - registry-vpc.cn-hangzhou.aliyuncs.com/pipeline-demo/base-image-1:debug
        - registry-vpc.cn-hangzhou.aliyuncs.com/pipeline-demo/base-image-2:debug
        # 基础镜像要缓存的路径。
        cacheDir: "/mnt/image-cache"
        # 指定ACR企业版实例。
        instanceID: cri-xxxx
  # 任务模板指定为内置的模板build-image-task。
  taskTemplate: build-image-task
  runAfters: []
- name: only-build
  context:
    data:
      enable: true
      # 指定构建信息。
      build: 
        # 指定dockerfile,使用代码仓库中的相对路径。不指定时默认为./Dockerfile。
        dockerfile: code/Dockerfile
        # 指定镜像名,必须是ACR镜像。
        image: registry-vpc.cn-hangzhou.aliyuncs.com/pipeline-demo/demo-repo:latest
        # 使用基础镜像的缓存路径。
        cacheDir: "/mnt/image-cache" 
  # 任务模板指定为内置的模板build-image-task。
  taskTemplate: build-image-task
  runAfters: [only-warm]

构建ACR企业版镜像

如果您使用ACR企业版实例,ACR企业版有网络的访问控制。

由于流水线默认执行环境不支持固定公网以及内网IP网段,因此流水线默认执行环境无法访问ACR企业版实例,需要使用流水线专有执行环境来访问您的ACR企业版实例。

流程介绍

  1. 使用流水线专有执行环境并且绑定VPC,VPC需要和您的ACR企业版实例网络互通,建议您直接使用ACR企业版实例所在的VPC以及交换机。您也可以指定其他VPC并且完成配置专有网络的访问控制。具体操作,请参见配置专有网络的访问控制

  2. 指定ACR企业版实例构建镜像。

  3. 建议您对镜像仓库开启镜像加速,并且镜像Tag指定_accelerated加速后缀。流水线镜像构建任务会自动推送原始的镜像并且等待加速镜像转换完成。更多信息,请参见按需加载容器镜像

YAML示例

kind: Pipeline
name: "image-build-use-cache-pipeline"
description: 'demo pipeline'
labels:
  myLabel: image-build-use-cache
spec:
  templateSpec:
    context:
      data:
        # 指定专有执行环境。
        runnerConfig:
          regionId: cn-hangzhou
          logConfig:
            project: demo-project
            logstore: demo-logstore
          # 网络配置,需要和ACR企业版实例网络互通。
          vpcConfig:
            securityGroupId: sg-xxxx
            vSwitchIds:
              - vsw-xxx
            vpcId: vpc-xxxx
          # 实例规格。
          cpu: 8
          memory: 32768
          diskSize: 10240
          # 构建超时时间。
          timeout: 1800
    tasks:
      - name: build-push
        context:
          data:
            # 任务显示名字,用于在控制台中展示。
            displayName: 镜像构建
            # 打开任务执行,默认关闭。
            enable: true
            # 指定构建信息。
            build:
              # 指定dockerfile,使用代码仓库中的相对路径。不指定时默认为./Dockerfile。
              dockerfile: code/Dockerfile
              # 指定镜像名,建议开启镜像加速,并且指定_accelerated加速后缀。
              image: demo-registry-vpc.cn-hangzhou.aliyuncs.com/pipeline***/demo***:debug_accelerated
              # 指定ACR企业版实例。
              instanceID: cri-xxxx
            
        # 任务模板指定为内置的模板build-image-task。
        taskTemplate: build-image-task
        runAfters: []

使用镜像构建和部署功能进行完整的CI/CD流程

推荐您使用镜像构建任务模板以及自定义任务模板完成构建、部署的自动化流程。

  • 每次CI过程都推荐为镜像打上新的Tag,并且Tag和本次Commit关联。

  • CD过程中使用全新的Tag部署。

通过下面的示例可以完成上述过程。

  • 对于构建任务,使用流水线YAML预置变量<% .git.shortCommitId %>作为镜像的Tag,该变量表示本次Git操作中HEAD Commit的CommitId的前7位,例如image: registry-vpc.cn-hangzhou.aliyuncs.com/demo/demo-image:<% .git.shortCommitId %>。流水线YAML内置变量,请参见使用YAML文件描述流水线

  • 对于部署任务,注入一个环境变量GIT_COMMIT,变量的值为<% .git.shortCommitId %>。

  • 修改s.yaml,将自定义镜像的Tag改成${env(GIT_COMMIT)},表示引用该环境变量。通过这种变量赋值,就可以让s.yaml动态修改部署镜像Tag。

完整示例如下。

  • 流水线YAML

    # 提交流水线执行。
    kind: Pipeline
    # 流水线执行名称,需要全局唯一。如果流水线模板存在,则不能成功提交流水线执行。
    # 推荐使用commitID与时间戳构造唯一的名称。
    name: "p-<% .git.shortCommitId %>-<% .currentTimestampMs %>"
    # 一些任意的描述信息。
    description: 'demo pipeline'
    # 添加任意的labels,用于查询过滤。
    # 应用中心会在提交时也会添加其他labels。
    labels:
      myLabel: my-cicd-example
    spec:
      context:
        data:
          appName: <% .appName %>
      templateSpec:
        context:
          data:
            envName: <% .envName %>
            deployFile: s.yaml
        tasks:
          # 镜像构建。
          - name: build-image
            context:
              data:
                displayName: 镜像构建
                enable: true
                build: # 镜像构建。
                  dockerfile: code/Dockerfile
                  # 使用 <% .git.shortCommitId %> 将tag和commit相关联。
                  image: registry-vpc.cn-hangzhou.aliyuncs.com/demo/demo-image:<% .git.shortCommitId %>
            taskTemplate: build-image-task
            runAfters: []
        	# 部署。
          - name: build-and-deploy
            context:
              data:
                displayName: 部署
                enable: true
                # 动态注入本次部署的环境变量。
                envVars:
                  GIT_COMMIT: <% .git.shortCommitId %>
                steps:
                  - plugin: "@serverless-cd/checkout"
                  - plugin: "@serverless-cd/s-setup"
                  - plugin: "@serverless-cd/s-deploy"
            taskTemplate: serverless-runner-task
            runAfters:
              - name: build-push
  • s.yaml

    edition: 3.0.0
    name: demo
    access: 'default'  #  密钥别名。
    
    resources:
      function: 
        component: fc3
        props:
          region: 'cn-hangzhou'
          functionName: demo
          runtime: custom-container
          customContainerConfig:
            # 引用部署任务注入的环境变量。
            image: registry-vpc.cn-hangzhou.aliyuncs.com/demo***/demo-ima***:${env(GIT_COMMIT)}
            port: 9000
          memorySize: 4096
          timeout: 3600