建立容器映像檔

本頁說明如何設定 Cloud Build,以建構及儲存 Docker 映像檔。如果您是 Cloud Build 新手,請先參閱快速入門導覽課程建構設定總覽

Cloud Build 提供預先建構的映像檔,您可以在 Cloud Build 設定檔中參照這些映像檔來執行工作。這些映像檔由 Google Cloud支援及維護。您可以使用支援的預先建構 Docker 映像檔執行 Docker 指令,並建構 Docker 映像檔。

事前準備

本頁的操作說明假設您已熟悉 Docker。此外:

  • 請準備好應用程式原始碼和 Dockerfile
  • 在 Artifact Registry 中建立 Docker 存放區來儲存映像檔,或建立新的存放區
  • 如要使用本頁的 gcloud 指令,請安裝 Google Cloud CLI
  • 如要執行映像檔,請安裝 Docker
  • 如要使用 cosign 簽署映像檔,請按照「授權服務對服務的存取權」一文中的操作說明,建立使用者指定的服務帳戶,並授予產生 ID 權杖所需的權限。

使用建構設定檔建構

如要使用建構設定檔建構 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 和原始碼位於不同目錄,請在 args 欄位的引數清單中新增 -fDockerfile 的路徑:

      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 執行這項操作。

如要使用建構套件建構,請從包含原始碼的目錄執行下列指令:

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

其中:

  • BUILDPACK_BUILDER:要使用的建構包建構工具。 如未指定建構工具,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'
    

設定觸發條件以使用建構包:除了使用指令列建構之外,您也可以設定觸發條件,讓系統使用建構包自動建構映像檔。詳情請參閱「建立及管理自動建構觸發條件」。

在 Artifact Registry 中儲存映像檔的不同方式

您可以透過下列方式,設定 Cloud Build 將建構的映像檔儲存在:

  • 建構完成後,使用 images 欄位將 Docker 映像檔儲存在 Artifact Registry 中。
  • 建構完成後,請使用 artifacts.oci 欄位將 OCI 映像檔儲存在 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. 使用建構設定檔展開建構作業:

    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. 使用建構設定檔展開建構作業:

    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. 使用建構設定檔展開建構作業:

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    其中:

    • CONFIG_FILE_PATH 是建構設定檔的路徑。
    • SOURCE_DIRECTORY 是原始碼的路徑或網址。

在建構完成後,將 OCI 映像檔儲存至 Artifact Registry

  1. 在含有應用程式原始碼和 Dockerfile 的同一個目錄中,建立名為 cloudbuild.yamlcloudbuild.json 的檔案。
  2. 在建構設定檔中,新增 artifacts 欄位,指定建構的 OCI 映像檔。這項設定會將 OCI 映像檔儲存在 Artifact Registry 中。下列範例顯示建構設定,該設定會建構 OCI 映像檔並儲存在 Artifact Registry 中:

    YAML

    artifacts:
      oci:
      - file: 'OCI_IMAGE_PATH'
        registryPath: 'https://LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY'
        tags: ["primary_image"]
    

    JSON

    {
      "artifacts": {
        "oci": [
          {
            "file": "OCI_IMAGE_PATH",
            "registryPath": "https://LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY",
            "tags": ["primary_image"]
          }
        ]
      }
    }
    

    其中:

    • OCI_IMAGE_PATH 是包含要上傳 OCI 映像檔的本機目錄位址,例如 /.pack/layout-repo/my-app
    • LOCATION 是存放區的區域或多區域位置。
    • PROJECT_ID 是您的 Google Cloud 專案 ID。
    • REPOSITORY:是 Artifact Registry 存放區的名稱。

使用 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"
      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-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.
    

後續步驟