本页面介绍了如何配置 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
- 如果您想使用联合签名对图片进行签名,请按照授权服务到服务访问权限中的说明创建用户指定的服务账号,并授予生成 ID 令牌所需的权限。
使用构建配置文件进行构建
如需使用构建配置文件构建 Docker 映像,请执行以下操作:
- 在应用源代码所在的目录中,创建一个名为
cloudbuild.yaml
或cloudbuild.json
的文件。 在构建配置文件中:
- 添加
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
和源代码位于不同的目录中,请将-f
和Dockerfile
的路径添加到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_PATH
:Dockerfile
的路径。
- 添加
使用构建配置文件启动构建:
gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
将上述命令中的占位值替换为以下内容:
CONFIG_FILE_PATH
:构建配置文件的路径。SOURCE_DIRECTORY
:源代码的路径或网址。
如果您未在
gcloud builds submit
命令中指定CONFIG_FILE_PATH
和SOURCE_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 description) 页面、Build.get()
的结果和 gcloud builds list
的结果。但是,如果使用 Docker push
命令来存储构建的映像,则映像将不会显示在构建结果中。
如果您希望将存储映像作为构建流程的一部分,并在构建结果中显示映像,请在构建配置文件中同时使用 Docker push
命令和 images
字段。
构建完成后将容器映像存储在 Artifact Registry 中 完成:
- 如果目标代码库不存在,请创建新代码库。
- 在应用源代码和
Dockerfile
所在的目录中,创建一个名为cloudbuild.yaml
或cloudbuild.json
的文件。 在构建配置文件中,添加构建步骤以构建映像,然后添加用于指定构建的映像的
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
:容器映像的名称。
使用构建配置文件启动构建:
gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
其中:
CONFIG_FILE_PATH
是构建配置文件的路径。SOURCE_DIRECTORY
是源代码的路径或网址。
如需在构建流程中将映像存储在 Artifact Registry 中,请执行以下操作:
在应用源代码和
Dockerfile
所在的目录中,创建一个名为cloudbuild.yaml
或cloudbuild.json
的文件。在构建配置文件中,添加一个
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
:容器映像的名称。
使用构建配置文件启动构建:
gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
其中:
CONFIG_FILE_PATH
是构建配置文件的路径。SOURCE_DIRECTORY
是源代码的路径或网址。
如需将存储映像作为构建流程的一部分,并在构建结果中显示映像,请执行以下操作:
- 在应用源代码和
Dockerfile
所在的目录中,创建一个名为cloudbuild.yaml
或cloudbuild.json
的文件。 在构建配置文件中,在用于构建映像的步骤之后,添加一个步骤来调用 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
:容器映像的名称。
使用构建配置文件启动构建:
gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
其中:
CONFIG_FILE_PATH
是构建配置文件的路径。SOURCE_DIRECTORY
是源代码的路径或网址。
使用协同签名为容器映像签名
如果将映像存储在 Artifact Registry 中,可以额外增加一层安全防护 使用 协同签名工具 创建用于启动构建作业的服务账号的记录。该记录由 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"
docker inspect $_IMAGE --format "$_IMAGE@{{.Id}}" >image_with_digest
- name: 'gcr.io/cloud-builders/gcloud'
id: 'generate-token'
script: |
#!/bin/sh
set -e
gcloud auth print-identity-token --audiences=sigstore > token
- name: 'gcr.io/cloud-builders/docker'
id: 'sign-image'
script: |
#!/bin/sh
set -e
docker run \
--network=cloudbuild \
--mount source=home-volume,target=/builder/home \
--rm \
-e SIGSTORE_NO_CACHE=true \
-e HOME=/builder/home \
gcr.io/projectsigstore/cosign \
sign --identity-token=$(cat token) $(cat image_with_digest) -y
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-east1
或us
。PROJECT_ID
:您的 Google Cloud 项目 ID。REPOSITORY
是存储了映像的代码库的名称。IMAGE_NAME
是映像的名称。SERVICE_ACCOUNT_ID
是您要用于运行 build 的用户指定服务账号的电子邮件地址。例如, 服务账号电子邮件地址的格式为: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 运行该映像。
将 Docker 配置为使用 Artifact Registry 凭据与 Artifact Registry 进行交互。(您只需执行此操作一次。)使用以下命令使用 gcloud 凭据帮助程序进行身份验证。
gcloud auth configure-docker HOSTNAME-LIST
其中 HOSTNAME-LIST 是要添加到凭据帮助程序配置的以英文逗号分隔的代码库主机名列表。
例如,如需添加区域
us-central1
和asia-northeast1
,请运行以下命令:gcloud auth configure-docker us-central1-docker.pkg.dev,asia-northeast1-docker.pkg.dev
运行之前构建的 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.
后续步骤
- 了解如何构建 Java 应用。
- 了解如何构建 Python 应用。
- 了解如何构建 Go 应用。
- 了解如何在 Cloud Storage 中存储构建工件。
- 了解如何在 Artifact Registry 中存储构建工件。
- 了解如何排查构建错误。