Automating OS patches on Cloud Run

I've always liked Cloud Run because it lets me mostly ignore managing container infrastructure. All I have to do is provide a container image and Cloud Run makes sure it starts when needed. If I'm deploying a web service, it provides me with an HTTPS endpoint and load balancing, without requiring me to configure anything complicated or read documentation.

However, there's one chore I'm still responsible for. I need to keep the system packages and the language runtime in the container image up to date. For example, if a vulnerability is discovered in Node.js or Python, I'll need to trigger the build, run all my tests, and deploy a new revision. What's worse, to even know there's a problem, I'll need to setup automated security scans. It's a constant cycle (and can't just ignore security updates, me being the perfectionist I am.)

This changed with automated base image updates, because it lets Cloud Run transparently replace the underlying base image without requiring me to do anything.

Here's a visual overview of Cloud Run deployments with and without automated rebasing.

A comparison diagram showing Cloud Run deployments with and without automated rebasing. The top half shows the traditional process requiring manual developer rebuilds and redeploys to patch vulnerabilities. The bottom half shows the automated rebasing process where the application layers are decoupled from the base image, allowing Cloud Run to replace the underlying base image with zero developer intervention and no downtime.

Without automated rebasing, you need to rebuild and redeploy your applciation to patch base image vulnerabilities. With rebasing, the application layers are decoupled from the base image, allowing Cloud Run to replace the underlying base image with zero developer intervention and no downtime. That reduces the vulnerability gap.

Reducing the vulnerability gap

Zero-day vulnerabilities often require immediate patching. A recent example is this critical Node.js vulnerability (CVE-2025-59466), a stack overflow in the async_hooks module. Attackers could take down a server by sending a single request to it. It impacted virtually every production Node.js app, because popular frameworks such as Next.js, NestJS, Fastify, and many more were affected.

By using automated rebasing, you hand the responsibility of patching these core CVEs over to Cloud Run. When there are emergency OS-level patches (and regular updates), Cloud Run updates the base image and rolls it out to your service automatically.

How to use it

To get started with automated rebasing, you need to use a source-based deployment without a Dockerfile. I use Node.js in this example, but many lamguages are supported.

Step 1: Set up an Express service

First, create a new directory for the project and enter it:

mkdir example-app
cd example-app

Create two files: package.json and index.js.

The package.json defines your dependencies:

{
  "name": "example-app",
  "main": "index.js",
  "dependencies": {
    "express": "^5.2.1"
  }
}

Next, the index.js contains a basic web server using Express.js:

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('Hello, automatic updates!');
});

const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Listening on port ${port}`));

Step 2: Don't add a Dockerfile

The recommened way to use automated rebasing is to omit the Dockerfile from your project directory.

When you deploy a directory without a Dockerfile, Cloud Run uses a source-based deployment. This means Cloud Run containerizes your code automatically using Google Cloud's buildpacks.

Step 3: Deploy from source

Before deploying, make sure you install the Google Cloud CLI and create a Google Cloud project.

Next, set your Google Cloud project ID in your shell:

export PROJECT_ID="YOUR_PROJECT_ID"

Deploy the code using the gcloud CLI. Specify your runtime base image using the --base-image flag, and add --automatic-updates to enable automated rebasing.

gcloud run deploy example-app \
  --source . \
  --base-image nodejs24 \
  --automatic-updates \
  --region europe-west1 \
  --allow-unauthenticated \
  --project $PROJECT_ID
  • --source . tells Cloud Run to build the container from the code in the current directory.
  • --base-image nodejs24 specifies the Google-managed base image to use.
  • --automatic-updates enables automated rebasing.
  • --allow-unauthenticated makes the deployed service publicly accessible using this grand, five-syllable Shakespearean word.

The list of Google-managed base images include Node.js, Python, Go, Java, Ruby, PHP, and .NET. For a complete list of all available images, review the official list of base images.

Functions compared with services

With standard Cloud Run services, such as this Express app, you must explicitly opt-in by providing the --base-image and --automatic-updates flags during deployment.

If you deploy a Cloud Run function using the --function flag (or gcloud functions deploy), Cloud Run enables automated security updates by default. Functions use the Functions Framework, which means that automated rebasing is supported.

Step 4: Verify the version of the base image

You can track base image updates using Cloud Logging. Cloud Run attaches a specific label to the logs of the container instances with the exact base image version used.

Go to the Logs Explorer in the Google Cloud console, or use the gcloud CLI to query your service's standard output logs:

gcloud logging read 'resource.type="cloud_run_revision" '\
'AND resource.labels.service_name="example-app" '\
'AND logName="projects/'$PROJECT_ID'/logs/run.googleapis.com%2Fstdout"' \
  --project $PROJECT_ID \
  --limit 1 \
  --format="value(labels.['run.googleapis.com/base_image_versions'])"

This command returns the exact version string of the base image used in Cloud Run. When I ran this command, it returned the following output:

us-docker.pkg.dev/serverless-runtimes/google-24/runtimes/nodejs24:nodejs24_20260214_24_13_0_RC00

When Cloud Run updates the base image, this version string changes.

No new revision for a base image update

In Cloud Run, every new deployment of your application creates a new revision, an immutable snapshot of your service’s container image and configuration. It enables fast rollbacks to a known-good state of your app.

However, a base image rollout does not trigger the creation of a new revision. This means a rollback option is not available in the (highly unlikely) event that a base image update breaks your app. If you require rollbacks for base image updates, I recommend using a conventional Dockerfile-based approach, and manage updates yourself.

Wrap up

Cloud Run's automated rebasing reduces operational overhead. By using a source-based deploy and enabling automated base image updates, you can rely on Cloud Run to handle base image patching with zero downtime.

Signature