构建容器映像

本页面介绍了如何配置 Cloud Build 来构建和存储 Docker 映像。如果您是刚接触 Cloud Build,请先阅读快速入门build 配置概览

Cloud Build 提供了预构建的映像,您可以在 Cloud Build 配置文件中引用这些映像来执行任务。这些映像由 Google Cloud 支持和维护。您可以使用受支持的预构建 Docker 映像执行 Docker 命令并构建 Docker 映像。

准备工作

本页面的说明假定您熟悉 Docker。此外:

  • 准备好应用源代码以及 Dockerfile
  • 拥有用于在 Artifact Registry 中存储映像的 Docker 代码库,或创建新的代码库
  • 如果要使用本页面中的 gcloud 命令,请安装 Google Cloud CLI
  • 如果要运行映像,请安装 Docker
  • 如果要使用 Cosign 为映像签名,请按照授权服务到服务访问权限中的说明创建用户指定的服务帐号,并授予生成 ID 令牌所需的权限。

使用 build 配置文件进行构建

如需使用构建配置文件构建 Docker 映像,请执行以下操作:

  1. 在应用源代码所在的目录中,创建一个名为 cloudbuild.yamlcloudbuild.json 的文件。
  2. 在构建配置文件中:

    • 添加 name 字段并指定预构建的 Docker 映像。预构建的映像存储在 gcr.io/cloud-builders/docker 中。在下面的示例配置文件中,name 字段指定 Cloud Build 使用预构建的 Docker 映像执行 args 字段指示的任务。
    • args 字段中,添加用于构建映像的参数。

      YAML

      steps:
      - name: 'gcr.io/cloud-builders/docker'
        args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.' ]
      

      JSON

      {
       "steps": [
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
              "build",
              "-t",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
              "."
             ]
         }
         ]
       }
      

      将上述构建配置中的占位符值替换为以下内容:

    • LOCATION:Artifact Registry 中 Docker 代码库的单区域或多区域位置。

    • PROJECT_ID:您的 Google Cloud 项目 ID。

    • REPOSITORY:Artifact Registry 中 Docker 代码库的名称。

    • IMAGE_NAME:容器映像的名称。

      如果您的 Dockerfile 和源代码位于不同的目录中,请将 -fDockerfile 的路径添加到 args 字段中的参数列表:

      YAML

      steps:
      - name: 'gcr.io/cloud-builders/docker'
        args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '-f', 'DOCKERFILE_PATH', '.' ]
      

      JSON

      {
       "steps": [
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
              "build",
              "-t",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME", '-f', 'DOCKERFILE_PATH', "."
             ]
         }
         ]
       }
      

      将上述构建配置中的占位符值替换为以下内容:

      • LOCATION:您的代码库的单区域或多区域位置。
      • PROJECT_ID:您的 Google Cloud 项目 ID。
      • REPOSITORY:您的 Artifact Registry 代码库的名称。
      • IMAGE_NAME:容器映像的名称。
      • DOCKERFILE_PATHDockerfile 的路径。
  3. 使用构建配置文件启动构建:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    将上述命令中的占位值替换为以下内容:

    • CONFIG_FILE_PATH:构建配置文件的路径。
    • SOURCE_DIRECTORY:源代码的路径或网址。

    如果您未在 gcloud builds submit 命令中指定 CONFIG_FILE_PATHSOURCE_DIRECTORY,则 Cloud Build 会假定配置文件和源代码位于当前工作目录中。

使用 Dockerfile 构建

Cloud Build 允许您仅使用 Dockerfile 构建 Docker 映像。您不需要单独的构建配置文件。

如需使用 Dockerfile 进行构建,请从包含源代码和 Dockerfile 的目录中运行以下命令:

    gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME

将上述命令中的占位值替换为以下内容:

  • LOCATION:您的代码库的单区域或多区域位置。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
  • REPOSITORY:您的 Artifact Registry 代码库的名称。
  • IMAGE_NAME:容器映像的名称。

使用 Google Cloud 的 Buildpack 进行构建

借助 Cloud Build,您可以在不使用 Dockerfile 或构建配置文件的情况下构建映像。您可以使用 Google Cloud 的 Buildpack 执行此操作。

如需使用 Buildpack 进行构建,请从包含源代码的目录运行以下命令:

    gcloud builds submit --pack builder=BUILDPACK_BUILDER, \
        env=ENVIRONMENT_VARIABLE, \
        image=IMAGE_NAME

将上述命令中的占位值替换为以下内容:

  • BUILDPACK_BUILDER:要使用的 Buildpack 构建器。如果您未指定构建器,Cloud Build 将默认使用 gcr.io/buildpacks/builder
  • ENVIRONMENT_VARIABLE:用于您的构建的任何环境变量。
  • IMAGE:Artifact Registry 中映像的网址。映像网址必须采用 LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME 格式。

以下是一些示例命令:

  • 使用默认 gcr.io/buildpacks/builder 运行构建以创建映像 us-docker.pkg.dev/gcb-docs-project/containers/gke/hello-app

      gcloud builds submit --pack image=us-docker.pkg.dev/gcb-docs-project/containers/gke/hello-app
    
  • 使用 ^--^ 作为分隔符以向您的构建传递多个环境变量。如需详细了解转义参数,请参阅 gcloud topic escaping

      gcloud builds submit --pack \
          ^--^image=gcr.io/my-project/myimage--env=GOOGLE_ENTRYPOINT='java -jar target/myjar.jar',GOOGLE_RUNTIME_VERSION='3.1.301'
    

将触发器配置为使用 buildpack:除了使用命令行构建之外,您还可以配置触发器以使用 buildpack 自动构建映像。如需了解详情,请参阅创建和管理构建触发器

在 Artifact Registry 中存储映像的不同方法

您可以将 Cloud Build 配置为通过以下方式之一存储构建的映像:

  • 使用 images 字段,该字段会在构建完成后将映像存储在 Artifact Registry 中。
  • 使用 docker push 命令,该命令将映像作为构建流程的一部分存储在 Artifact Registry 中。

使用 images 字段和 Docker push 命令之间的区别在于,如果使用 images 字段,则存储的映像将显示在构建结果中。这包括 Google Cloud 控制台中构建的构建说明页面、Build.get() 的结果以及 gcloud builds list 的结果。但是,如果使用 Docker push 命令来存储构建的映像,则映像将不会显示在构建结果中。

如果您希望将存储映像作为构建流程的一部分,并在构建结果中显示映像,请在构建配置文件中同时使用 Docker push 命令和 images 字段。

如需在构建完成后将容器映像存储在 Artifact Registry 中,请执行以下操作

  1. 如果目标代码库不存在,请创建新代码库
  2. 在应用源代码和 Dockerfile 所在的目录中,创建一个名为 cloudbuild.yamlcloudbuild.json 的文件。
  3. 在构建配置文件中,添加构建步骤以构建映像,然后添加用于指定构建的映像的 images 字段。这会将映像存储在 Artifact Registry 中。以下代码段展示了用于构建映像并将其存储在 Artifact Registry 中的构建配置:

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.' ]
    images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    

    JSON

    {
    "steps": [
    {
        "name": "gcr.io/cloud-builders/docker",
        "args": [
            "build",
            "-t",
            "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
            "."
        ]
    }
    ],
    "images": [
        "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
    ]
    }
    

    其中:

    • LOCATION:您的代码库的单区域或多区域位置。
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REPOSITORY:您的 Artifact Registry 代码库的名称。
    • IMAGE_NAME:容器映像的名称。
  4. 使用 build 配置文件启动构建:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    其中:

    • CONFIG_FILE_PATH 是构建配置文件的路径。
    • SOURCE_DIRECTORY 是源代码的路径或网址。

如需在构建流程中将映像存储在 Artifact Registry 中,请执行以下操作

  1. 在应用源代码和 Dockerfile 所在的目录中,创建一个名为 cloudbuild.yamlcloudbuild.json 的文件。

  2. 在构建配置文件中,添加一个 docker 构建步骤以构建映像,然后添加另一个 docker 构建步骤并传递参数以调用 push 命令:

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.']
    - name: 'gcr.io/cloud-builders/docker'
      args: ['push', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    

    JSON

    {
      "steps": [
       {
          "name": "gcr.io/cloud-builders/docker",
          "args": [
              "build",
              "-t",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
              "."
           ]
       },
       {
           "name": "gcr.io/cloud-builders/docker",
           "args": [
              "push",
              "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
            ]
       }
      ]
    }
    

    其中:

    • LOCATION:您的代码库的单区域或多区域位置。
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REPOSITORY:您的 Artifact Registry 代码库的名称。
    • IMAGE_NAME:容器映像的名称。
  3. 使用 build 配置文件启动构建:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    其中:

    • CONFIG_FILE_PATH 是构建配置文件的路径。
    • SOURCE_DIRECTORY 是源代码的路径或网址。

如需将存储映像作为构建流程的一部分,并在构建结果中显示映像,请执行以下操作

  1. 在应用源代码和 Dockerfile 所在的目录中,创建一个名为 cloudbuild.yamlcloudbuild.json 的文件。
  2. 在构建配置文件中,在用于构建映像的步骤之后,添加一个步骤来调用 Docker push 命令,然后添加 images 字段:

    YAML

    steps:
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME', '.']
    - name: 'gcr.io/cloud-builders/docker'
      args: ['push', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME']
    

    JSON

    {
        "steps": [
       {
           "name": "gcr.io/cloud-builders/docker",
           "args": [
               "build",
               "-t",
               "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
               "."
            ]
       },
       {
           "name": "gcr.io/cloud-builders/docker",
           "args": [
               "push",
               "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
            ]
       }
       ],
        "images": [
           "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME"
        ]
    }
    

    其中:

    • LOCATION:您的代码库的单区域或多区域位置。
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REPOSITORY:您的 Artifact Registry 代码库的名称。
    • IMAGE_NAME:容器映像的名称。
  3. 使用 build 配置文件启动构建:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    其中:

    • CONFIG_FILE_PATH 是构建配置文件的路径。
    • SOURCE_DIRECTORY 是源代码的路径或网址。

使用 Cosign 对容器映像进行签名

如果您在 Artifact Registry 中存储映像,则可以使用 cosign 工具创建记录来记录启动构建时使用的服务帐号,从而额外增加一层安全保障。在 OpenID Connect (OIDC) 标准的支持下,审核人员可以使用该记录来验证映像是否由受信任的服务帐号构建。

以下步骤演示了如何使用 cloudbuild.yaml 配置文件获取身份令牌并为容器映像签名。

YAML

  steps:
  - name: 'gcr.io/cloud-builders/docker'
    id: 'tag-and-push'
    script: |
      #!/bin/sh
      set -e
      docker build -t $_IMAGE .
      docker push "$_IMAGE"
  - name: 'gcr.io/cloud-builders/gcloud'
    id: 'generate-token-and-get-digest'
    script: |
      #!/bin/sh
      set -e
      gcloud auth print-identity-token --audiences=sigstore > token
      gcloud container images describe "$_IMAGE" \
        --format="value(image_summary.fully_qualified_digest)" > image_with_digest
  - name: 'gcr.io/projectsigstore/cosign'
    id: 'sign-image'
    script: |
      #!/busybox/sh
      cosign sign --identity-token=$(cat token) $(cat image_with_digest) -y
    env:
    - 'SIGSTORE_NO_CACHE=true'
  service_account: '$_SERVICE_ACCOUNT'
  artifacts:
    images:
    - $_IMAGE
  substitutions:
    _IMAGE: 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME'
    _SERVICE_ACCOUNT_ID: 'SERVICE_ACCOUNT_ID'
    _SERVICE_ACCOUNT: projects/${PROJECT_ID}/serviceAccounts/${_SERVICE_ACCOUNT_ID}
  options:
    env:
    - '_IMAGE=$_IMAGE'
    dynamic_substitutions: true
    logging: CLOUD_LOGGING_ONLY

JSON

    {
        "steps": [
            {
                "name": "gcr.io/cloud-builders/docker",
                "id": "tag-and-push",
                "script": "#!/bin/sh set -e \ndocker build -t $_IMAGE . \ndocker push \"$_IMAGE\""
            },
            {
                "name": "gcr.io/cloud-builders/gcloud",
                "id": "generate-token-and-get-digest",
                "script": "#!/bin/sh set -e \ngcloud auth print-identity-token --audiences=sigstore > token \ngcloud container images describe \"$_IMAGE\" --format=\"value(image_summary.fully_qualified_digest)\" > image_with_digest"
            },
            {
                "name": "gcr.io/projectsigstore/cosign",
                "id": "sign-image",
                "script": "#!/busybox/sh cosign sign --identity-token=$(cat token) $(cat image_with_digest) -y",
                "env": [
                    "SIGSTORE_NO_CACHE=true"
                ]
            }
        ],
        "service_account": "$_SERVICE_ACCOUNT",
        "artifacts": {
            "images": [
                "$_IMAGE"
            ]
        },
        "substitutions": {
            "_IMAGE": "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME",
            "_SERVICE_ACCOUNT_ID": "SERVICE_ACCOUNT_ID",
            "_SERVICE_ACCOUNT": "projects/${PROJECT_ID}/serviceAccounts/${_SERVICE_ACCOUNT_ID}"
        },
        "options": {
            "env": [
                "_IMAGE=$_IMAGE"
            ],
            "dynamic_substitutions": true,
            "logging": "CLOUD_LOGGING_ONLY"
        }
    }

其中:

  • LOCATION 是存储映像的代码库的单区域或多区域位置,例如 us-east1us

  • PROJECT_ID:您的 Google Cloud 项目 ID。

  • REPOSITORY 是存储映像的代码库的名称。

  • IMAGE_NAME 是映像的名称。

  • SERVICE_ACCOUNT_ID 是您要运行构建的用户指定服务帐号的电子邮件地址。例如,服务帐号电子邮件地址如下所示:service-account-name@project-id.iam.gserviceaccount.com

如需验证签名,请在本地机器上安装 cosign,然后运行 cosign verify 命令:

cosign verify \
--certificate-identity=SERVICE_ACCOUNT_ID \
--certificate-oidc-issuer=https://accounts.google.com \
IMAGE

其中:

  • SERVICE_ACCOUNT_ID 是您希望用于构建容器映像的可信服务帐号的电子邮件地址。
  • IMAGE 是包含 sha256 映像摘要的完整映像名称。

运行 Docker 映像

要验证您构建的映像是否按预期正常运行,可使用 Docker 运行该映像。

  1. 将 Docker 配置为使用 Artifact Registry 凭据与 Artifact Registry 交互。(您只需执行此操作一次。)使用以下命令通过 gcloud 凭据帮助程序进行身份验证。

    gcloud auth configure-docker HOSTNAME-LIST
    

    其中 HOSTNAME-LIST 是要添加到凭据帮助程序配置的代码库主机名的列表(以英文逗号分隔)。

    例如,如需添加区域 us-central1asia-northeast1,请运行以下命令:

    gcloud auth configure-docker us-central1-docker.pkg.dev,asia-northeast1-docker.pkg.dev
    
  2. 运行之前构建的 Docker 映像:

    docker run LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME
    

    其中:

    • LOCATION:您的代码库的单区域或多区域位置。
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REPOSITORY:您的 Artifact Registry 代码库的名称。
    • IMAGE_NAME:容器映像的名称。

    您将看到如下所示的输出:

    Hello, world! The time is Fri Feb  2 16:09:54 UTC 2018.
    

后续步骤