コンテナ イメージのビルド

このページでは、Docker イメージをビルドして格納するように Cloud Build を構成する方法について説明します。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.yaml または cloudbuild.json という名前でファイルを作成します。
  2. ビルド構成ファイルで、次のことを行います。

    • name フィールドを追加し、事前にビルドされている Docker イメージを指定します。事前にビルドされたイメージは gcr.io/cloud-builders/docker に保存されます。以下の構成ファイルの例では、name フィールドは、args フィールドで示されるタスクを実行するために、ビルド済みの Docker イメージを Cloud Build が使用することを指定します。
    • 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_PATH: Dockerfile へのパス。
  3. ビルド構成ファイルを使用してビルドを開始します。

    gcloud builds submit --config CONFIG_FILE_PATH SOURCE_DIRECTORY
    

    上記のコマンドのプレースホルダ値を次のように置き換えます。

    • CONFIG_FILE_PATH: ビルド構成ファイルのパス。
    • SOURCE_DIRECTORY: ソースコードのパスまたは URL。

    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 の Buildpacks を使用してビルドする

Cloud Build では、Dockerfile やビルド構成ファイルを使用せずにイメージをビルドできます。これは、Google Cloud の Buildpacks を使用して行うことができます。

Buildpacks を使用してビルドするには、ソースコードが格納されているディレクトリから次のコマンドを実行します。

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

上記のコマンドのプレースホルダ値を次のように置き換えます。

  • BUILDPACK_BUILDER: 使用する buildpacks ビルダー。ビルダーを指定しない場合、Cloud Build はデフォルトで gcr.io/buildpacks/builder を使用します。
  • ENVIRONMENT_VARIABLE: ビルドの環境変数。
  • IMAGE: Artifact Registry のイメージの URL。画像の URL は 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'
    

Buildpacks を使用するようにトリガーを構成する: コマンドラインを使用してビルドするだけでなく、Buildpacks を使用してイメージを自動的にビルドするようにトリガーを構成できます。詳しくは、ビルドトリガーの作成と管理をご覧ください。

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.yaml または cloudbuild.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 は、ソースコードへのパスまたは URL です。

ビルドフローの中で Artifact Registry にイメージを格納するには次のことを行います

  1. アプリケーションのソースコードと Dockerfile が含まれているディレクトリに、cloudbuild.yaml または cloudbuild.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 は、ソースコードへのパスまたは URL です。

ビルドフローの中でイメージを格納し、ビルド結果にイメージを表示するには次のことを行います

  1. アプリケーションのソースコードと Dockerfile が含まれているディレクトリに、cloudbuild.yaml または cloudbuild.json という名前でファイルを作成します。
  2. ビルド構成ファイルで、push コマンドを呼び出す Docker 起動ステップをイメージのビルドステップの後に追加し、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 は、ソースコードへのパスまたは URL です。

cosign を使用してコンテナ イメージに署名する

Artifact Registry にイメージを保存している場合は、cosign ツールを使用してビルドの開始に使用するサービス アカウントの記録を作成することで、別のセキュリティ レイヤを追加できます。OpenID Connect(OIDC)標準に基づく監査者は、その記録を使用してイメージが信頼できるサービス アカウントによってビルドされていることを確認できます。

以下の手順では、cloudbuild.yaml 構成ファイルを使用して ID トークンを取得し、コンテナ イメージに署名する方法を示します。

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. Artifact Registry を操作するときに Artifact Registry 認証情報を使用するように Docker を構成します。(この操作は初回のみ必要です。)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.
    

次のステップ