ベースイメージの自動更新を構成する

Cloud Run のベースイメージの自動更新を構成すると、Google はベースイメージのオペレーティング システムと言語ランタイム コンポーネントにセキュリティ パッチを自動的に適用できます。ベースイメージを更新するためにサービスを再ビルドまたは再デプロイする必要はありません。ベースイメージが更新されても、新しいリビジョンは作成されません。

次の図は、アプリケーション コードと依存関係(「アプリイメージ」)が、言語ランタイム、OS パッケージ、オペレーティング システム(「ベースイメージ」)の上にレイヤ化される方法を示しています。ベースイメージのコンポーネントは Google によって自動的に更新されます。

Cloud Run ベースイメージの図

ベースイメージの自動更新を構成するには、次の操作を行います。

  • 互換性のある Cloud Run ベースイメージを選択します。
  • 実行中のサービスを安全にリベースできるように、アプリケーション イメージをビルドしてデプロイします。

ベースイメージを選択する

ほとんどのコンテナベースの開発ワークフローでは、ベースイメージが出発点になります。デベロッパーは、ベースイメージから始めて、その上にアプリケーションの実行に使用されるライブラリ、バイナリ、構成ファイルを配置します。

Google Cloud の Buildpack は、サーバーレス アプリケーションのビルド用のベースイメージを公開して管理します。これらのベースイメージは、Ubuntu Linux ディストリビューション上に構築されています。

Cloud Run は、Google Cloud の Buildpack ベースイメージを使用する自動ベースイメージのみをサポートしています。

Google Cloud の Buildpack を選択する際は、次の点を考慮する必要があります。

  • スタック: スタックは、Linux ディストリビューション バージョンとシステム パッケージ(OpenSSL や curl など)で構成されます。
  • 言語: アプリで使用されるプログラミング言語の特定のバージョン

ベースイメージのバリエーションの詳細については、ランタイム ベースイメージをご覧ください。

アプリケーション イメージのビルド

自動更新が有効になっているサービスでは、ベースのオペレーティング システム レイヤのないアプリケーション イメージを提供する必要があります。これには次の 2 つの方法があります。

ソースからのデプロイ

Cloud Run のソースからのデプロイ機能を使用してコードをビルドしてデプロイすると、サービスが自動更新の受信に対応できるようになります。そのためには、アプリの作成時に --base-image フラグを指定する必要があります。

たとえば、ベースイメージの自動更新を有効にして Node.js サービスまたは関数をデプロイするには、次のコマンドを使用します。

gcloud beta run deploy \
  --source . \
  --base-image nodejs20

scratch 上にビルド

ビルド ツールチェーンを使用して、ベースイメージの自動更新と互換性のあるアプリケーション コンテナ イメージを作成することもできます。

ベースイメージの自動更新を使用して Cloud Run サービスをデプロイすると、アプリケーション コンテナ イメージがベースコンテナ イメージの上にレイヤ化されます。アプリケーション コンテナ イメージには、ベースコンテナ イメージで提供されるオペレーティング システムやランタイムではなく、アプリケーションのみを含める必要があります。

アプリケーション コンテナ イメージを作成するには、次の操作を行います。

  1. 次のようなマルチステージ Dockerfile を作成します。
    1. 必要な依存関係を含む適切なベースイメージを使用してアプリケーションをビルドします。
    2. ビルドされたコンポーネントをスクラッチ イメージにコピーします。
  2. アプリケーション コンテナ イメージをビルドして Artifact Registry に push します。
  3. アプリケーション コンテナ イメージを Cloud Run にデプロイし、ベースイメージを指定します。

マルチステージ Dockerfile を作成する

このガイドでは、Node.js アプリケーションを使用します。このガイドは言語に依存せず、アプリケーションと言語に合わせてカスタマイズできます。

  • プロジェクトのルート ディレクトリに、次の内容の Dockerfile を作成します。

    # This Dockerfile will produce an image that only includes the Node.js app and *not* the Node.js runtime.
    # The resulting image will not run locally. It is intented at being layered on top of a Node.js base image.
    
    FROM node:20-slim as builder
    
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    
    # Copy application dependency manifests to the container image and install
    # production dependencies.
    COPY package*.json ./
    RUN npm install --only=production
    
    # Copy local code to the container image.
    COPY . ./
    
    # Copy the application source code and depenencies onto a scratch image.
    FROM scratch
    WORKDIR /workspace
    COPY --from=builder --chown=33:33 /usr/src/app/ ./
    
    # Run the web service on container startup.
    CMD [ "node", "index.js" ]
    

この Dockerfile では、マルチステージ ビルドを使用して、アプリケーションのソースコードと依存関係を scratch イメージにコピーします。このイメージには、Cloud Run マネージド ベースイメージによって実行時に提供されるオペレーティング システム、パッケージ、ランタイム コンポーネントが含まれていません。

アプリケーション イメージのビルド

アプリケーション イメージをビルドして Artifact Registry にアップロードします。Cloud Build で Dockerfile をビルドして Artifact Registry にアップロードする方法については、コンテナのビルドをご覧ください。

アプリケーション イメージをデプロイする

これで、アプリケーションに最も適したベースイメージを使用して、自動更新を有効にし、アプリケーション イメージをデプロイする準備が整いました。この例では、us-central1 の Node.js 20 ランタイムを使用します。ベースイメージのバリエーションの詳細については、ランタイム ベースイメージをご覧ください。

必要なロールと権限の詳細については、Cloud Run へのコンテナ イメージのデプロイをご覧ください。

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. アプリケーション イメージのデプロイ中に Node.js 20 ランタイムの自動更新を有効にするには、次のコマンドを実行します。

    gcloud beta run deploy SERVICE \
    --image APP_IMAGE \
    --base-image BASE_IMAGE

    次のように置き換えます。

    • SERVICE は、デプロイ先のサービスの名前に置き換えます。
    • APP_IMAGE は、アプリケーション コンテナ イメージの URL に置き換えます。
    • BASE_IMAGE は、ベースイメージの URL(nodejs20 など)に置き換えます。us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs20 ベースイメージのバリエーションの詳細については、ランタイム ベースイメージをご覧ください。

YAML

  1. 新しいサービスを作成する場合は、この手順をスキップします。既存のサービスを更新する場合は、その YAML 構成をダウンロードします。

    gcloud run services describe SERVICE --format export > service.yaml
  2. runtimeClassNamerun.googleapis.com/base-images アノテーションを更新します。

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
    name: SERVICE
    annotations:
      ...
      run.googleapis.com/launch-stage: BETA
      ...
    spec:
    template:
      metadata:
        annotations:
          run.googleapis.com/base-images: '{"NAME":"BASE_IMAGE"}'
        spec:
          containers:
          - name: NAME
            image: APP_IMAGE
          runtimeClassName: run.googleapis.com/linux-base-image-update

    次のように置き換えます。

    • SERVICE は、デプロイ先のサービスの名前に置き換えます。
    • APP_IMAGE は、アプリケーション コンテナ イメージの URL に置き換えます。
    • BASE_IMAGE は、ベースイメージの URL(us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs20 など)に置き換えます。ベースイメージのバリエーションの詳細については、ランタイム ベースイメージをご覧ください。

コンテナ イメージを再構成してローカルで実行する

ベースイメージの自動更新で使用されるアプリケーション コンテナ イメージは scratch でビルドされ、ベースイメージの更新が有効になっている Cloud Run の外部では実行できません。アプリケーション イメージを実行可能にするには、アプリケーション イメージを互換性のあるベースイメージにリベースします。

  1. Docker Community Edition(CE)をワークステーションにインストールします。

  2. アプリケーション イメージをダウンロードします。

    docker pull APP_IMAGE
    

    次のように置き換えます。

    • APP_IMAGE は、コンテナ イメージの URL に置き換えます。
  3. ベースイメージをダウンロードします。

    docker pull BASE_IMAGE
    

    次のように置き換えます。

    • BASE_IMAGE は、互換性のあるベースイメージの URL に置き換えます。使用可能なベースイメージの一覧については、Google Cloud の Buildpack ベースイメージをご覧ください。たとえば、google-22 スタックを使用して Node.JS 20 アプリケーションを作成した場合は、us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs20:latest を選択します。
  4. イメージを再アセンブルします。

    Dockerfile を使用して、アプリイメージからベースイメージにすべてのファイルをコピーします。

    ARG APP_IMAGE
    ARG NEW_BASE_IMAGE
    
    # first copy all files from the app image onto the builder image
    FROM ${APP_IMAGE} AS app
    FROM ${NEW_BASE_IMAGE} AS builder
    COPY --from=app / /
    
    # restore the app image config by copying everything from previous step back
    # back onto the app image
    FROM ${APP_IMAGE}
    COPY --from=builder / /
    

    イメージをビルドします。

    docker build \
        -t IMAGE \
        --build-arg APP_IMAGE=APP_IMAGE \
        --build-arg NEW_BASE_IMAGE=BASE_IMAGE \
        .
    

    次のように置き換えます。

    • IMAGE は、再構成したイメージの名前に置き換えます。

    ARG ${APP_IMAGE}ARG ${NEW_BASE_IMAGE} が有効なベースイメージではないという警告が表示された場合は、無視してイメージを実行できます。

    docker run -p 8080:8080 IMAGE
    

自動アップデートを無効にする

ソースからデプロイする場合

ソースからデプロイする場合は、--no-automatic-updates フラグを使用してベースイメージの自動更新を無効にできます。次の例は、Node.js サービスのベースイメージの自動更新を無効にする方法を示しています。

gcloud

gcloud beta run deploy SERVICE \
    --source . \
    --base-image nodejs20 \
    --no-automatic-updates

コンテナ イメージをデプロイする場合

スクラッチでビルドされたコンテナ イメージを使用するサービスのベースイメージの更新を無効にするには、ベースイメージを含む新しいコンテナ イメージをデプロイし、ベースイメージを削除する必要があります。

gcloud

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. ベースイメージの自動更新を無効にするには、次のコマンドを実行します。

    gcloud beta run deploy SERVICE \
        --image IMAGE \
        --base-image ""

    次のように置き換えます。

    • SERVICE は、デプロイ先のサービスの名前に置き換えます。
    • IMAGE: アプリ、ランタイム、OS を含むコンテナ イメージの URL。

YAML

  1. 新しいサービスを作成する場合は、この手順をスキップします。既存のサービスを更新する場合は、その YAML 構成をダウンロードします。

    gcloud run services describe SERVICE --format export > service.yaml
  2. run.googleapis.com/base-images アノテーションを削除します。

  3. runtimeClassName 属性を削除します。

  4. image では、アプリ、ランタイム、OS を含むコンテナ イメージを使用してください。

  5. 次のコマンドを使用して、サービスを作成または更新します。

    gcloud run services replace service.yaml

既知の制限事項

  • ベースイメージの自動更新は、Google Cloud の Buildpack ベースイメージのみをサポートしています。独自のベースイメージを使用することはできません。

  • コンパイル済み言語を使用するアプリケーションは、ベースイメージの自動更新の結果として再コンパイルされません。

  • アプリケーション イメージのセキュリティ スキャンが完了していない可能性があります。アプリケーション イメージが scratch でビルドされるため、セキュリティ スキャナはイメージのアプリケーション部分のみをスキャンします。コンテナ セキュリティの完全なイメージを取得するには、対応する Google 提供のベースイメージでもスキャンを実行する必要があります。ベースイメージをダウンロードし、オープンソース ツールを使用してスキャンを実行できます。