Configure automatic base image updates

Configuring automatic base image updates for Cloud Run enables Google to make security patches to the operating system and language runtime components of the base image automatically. You don't have to rebuild or redeploy your service for the base image to be updated. No new revision is created when the base image is update.

The following diagram shows how your application code and dependencies ("app image") are layered on top of the language runtime, OS packages and Operating System ("base image"). The components of the base image are automatically updated by Google.

Cloud Run base image diagram

To configure automatic base image updates, do the following:

  • Select a compatible Cloud Run base image.
  • Build and deploy your application image in a way that preserves the ability to safely rebase your running service.

Select a Base Image

A base image is the starting point for most container-based development workflows. Developers start with a base image and layer on top of it the necessary libraries, binaries, and configuration files used to run their application.

Google Cloud's buildpacks publishes and maintains base images for building Serverless applications. These base images are built on top of the Ubuntu Linux distribution.

Cloud Run only supports automatic base images that use Google Cloud's buildpacks base images.

You must consider the following when choosing a Google Cloud's buildpacks:

  • Stack: A stack is made up of a Linux distribution version and system packages, such as OpenSSL and curl
  • Language: The specific version of the programming language used by your application

Review runtime base images to learn more about base image variations.

Building the application image

Services with automatic updates enabled will need to provide an application image that omits the base operating system layers. There are two ways to do this:

Deploy from source

You can use the Cloud Run deploy from source feature to build and deploy your code so that your service is compatible with receiving automatic updates. To do this, you must supply the --base-image flag when creating your application.

For example, to deploy a Node.js service or function with automatic base image updates enabled, you would use the following command:

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

Build on scratch

You can also use your build toolchain to create an application container image that is compatible with automatic base image updates.

When you deploy a Cloud Run service with automatic base image updates, your application container image is layered on top of a base container image. The application container image should only include your application, not the operating system or runtime, which are provided in the base container image.

To create the application container image, do the following:

  1. Create a multi-stage Dockerfile that:
    1. Builds the application using an appropriate base image with required dependencies.
    2. Copies the built components onto a scratch image.
  2. Build the application container image and push it to Artifact Registry.
  3. Deploy the application container image to Cloud Run and specify a base image.

Create a multi-stage Dockerfile

We will use a Node.js application for this guide. This guide is not language specific, and can be customized for your application and language.

  • Create a Dockerfile in the root directory of our project with the following:

    # 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
    COPY --from=builder --chown=33:33 /usr/src/app/ ./
    
    # Run the web service on container startup.
    CMD [ "node", "index.js" ]
    

This Dockerfile uses a multi-stage build to copy the application source code and dependencies onto a scratch image that omits the operating system, packages, and runtime components that will be supplied at runtime by the Cloud Run managed base image.

Building your application image

Build your application image and upload it into Artifact Registry. Refer to building containers for details on how to build a Dockerfile with Cloud Build and uploading it to Artifact Registry.

Deploy the application image

You are now ready to deploy your application image with automatic updates enabled using the most compatible base image for your application. We will use the Node.js 20 runtime from us-central1 for this example. Review runtime base images to learn more about base image variations.

Refer to deploying container images to Cloud Run for additional details on required roles and permissions.

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. To enable automatic updates for the Node.js 20 runtime while deploying your application image, run the following command:

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

    Replace:

    • SERVICE with the name of the service you want to deploy to.
    • APP_IMAGE with the URL of your application container image.
    • BASE_IMAGE with the URL of your base image, for example nodejs20 or us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs20 Review Runtime base images to learn more about base image variations.

YAML

  1. If you are creating a new service, skip this step. If you are updating an existing service, download its YAML configuration:

    gcloud run services describe SERVICE --format export > service.yaml
  2. Update runtimeClassName and the run.googleapis.com/base-images annotations:

    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
    

    Replace:

    • SERVICE with the name of the service you want to deploy to.
    • APP_IMAGE with the URL of your application container image.
    • BASE_IMAGE with the URL of your base image, for example us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs20. Review Runtime base images to learn more about base image variations.

Reassemble container images to run locally

Application container images used with automatic base image updates are built on scratch and cannot be run outside of Cloud Run with base image updates enabled. You can make your application image runnable by rebasing the application image on top of a compatible base image.

  1. Install Docker Community Edition (CE) on your workstation.

  2. Download the application image

    docker pull APP_IMAGE
    

    Replace:

    • APP_IMAGE with the URL of your container image.
  3. Download the base image:

    docker pull BASE_IMAGE
    

    Replace:

    • BASE_IMAGE with the URL of a compatible base image. The list of available base images can be found in Google Cloud's buildpacks base images. For example, if you created a Node.JS 20 application using the google-22 stack would select us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs20:latest.
  4. Reassemble the image

pack CLI

  1. Install the Pack CLI.

  2. Use pack rebase to combine the images:

    pack rebase $APP_IMAGE \
        --run-image=$NEW_BASE_IMAGE \
        --force
    

Docker

Use a Dockerfile to copy all the files from the app image back onto the base image:

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 / /

Build the image:

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

Disable automatic updates

When deploying from source

When deploying from source, you can disable automatic base image updates by using the --no-automatic-updates flag. The following example shows how to disable automatic base image updates for a Node.js service:

gcloud

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

When deploying a container image

To disable base image updates for a service that uses a container image built on scratch, you must deploy a new container image that includes the base image and remove the base image:

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. To disable automatic base image updates, run the following command:

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

    Replace:

    • SERVICE with the name of the service you want to deploy to.
    • IMAGE with the URL of your container image containing the app, runtime and OS.

YAML

  1. If you are creating a new service, skip this step. If you are updating an existing service, download its YAML configuration:

    gcloud run services describe SERVICE --format export > service.yaml
  2. Delete the run.googleapis.com/base-images annotation.

  3. Delete the runtimeClassName attribute.

  4. In image, make sure to use a container image that includes the app, runtime, and OS.

  5. Create or update the service using the following command:

    gcloud run services replace service.yaml

Known limitations

  • Automatic base image updates only support Google Cloud's buildpacks base images. It is not possible to use your own base images.

  • Applications using compiled languages won't be recompiled as a result of a automatic base image update.

  • Security scans on your application image might be incomplete. Because your application image is now built on scratch, security scanners will only scan the application portion of your image. To get a more complete image of your container security, you must run scans on the corresponding Google-provided base image as well. You can download the base image and use open source tools to run a scan.