First look at Cloud Run instances

Sometimes you want to run a single container in the cloud without an autoscaler spinning up extra copies or shutting down the instance while you work on it. With standalone Cloud Run instances in public preview, you can start an individual container, connect over SSH, and stop and start it on demand.

Until now, Cloud Run offered three ways to run containers on Google Cloud: services (which autoscale based on incoming HTTP requests), jobs (which run batch tasks to completion), and worker pools (which run fixed or autoscaled pools of background workers that don't need HTTP ingress). A standalone Cloud Run instance (gcloud beta run instances) gives you one container with its own lifecycle (create, stop, start, and restart), an optional run.app HTTPS URL, and SSH enabled by default.

Here's how to use Cloud Run instances across three practical workflows (an on-demand Linux box, a persistent workspace backed by a Cloud Storage bucket, and a singleton web server), followed by a look at regional availability, shared-CPU bursting, and pricing.

Running an on-demand Linux box

To spin up an Ubuntu workstation without exposing an HTTP port, you create a dedicated service account, launch an instance running sleep infinity with --no-default-url, and connect using SSH.

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

export PROJECT_ID="YOUR_PROJECT_ID"

By default, Cloud Run workloads run as the Compute Engine default service account, which usually has broad permissions across your project (so any process or compromised package inside the container could access or modify unrelated cloud resources). Create a dedicated, least-privilege service account for the instance instead:

gcloud iam service-accounts create dev-box-sa \
  --display-name="Cloud Run dev box service account" \
  --project=$PROJECT_ID
Created service account [dev-box-sa].

Next, create a dev-box instance in europe-west4 using the ubuntu:24.04 image:

gcloud beta run instances create dev-box \
  --image=ubuntu:24.04 \
  --command=sleep \
  --args=infinity \
  --no-default-url \
  --service-account=dev-box-sa@$PROJECT_ID.iam.gserviceaccount.com \
  --region=europe-west4 \
  --project=$PROJECT_ID
  • --image=ubuntu:24.04 pulls the official Ubuntu 24.04 image from Docker Hub.
  • --command=sleep and --args=infinity keep the container's initial process (PID 1) alive indefinitely.
  • --no-default-url disables the run.app HTTPS endpoint since this instance only accepts SSH connections.
  • --service-account assigns the dedicated service account dev-box-sa to the container.
  • --region=europe-west4 places the instance in the Netherlands. As of October 2026, Cloud Run instances are available in most regions except europe-west1, us-central1, and us-east1 (see Regional availability, CPU bursting, and pricing below).

Creating the instance imports the container image, provisions a lightweight virtual machine (microVM) on Cloud Run's second-generation execution environment, and prints the gcloud beta run instances ssh command to connect:

Creating Cloud Run instance [dev-box] in project [YOUR_PROJECT_ID] region [europe-west4]
Creating instance...
  Importing container... Imported container image in 6.58s....done
  Provisioning resources... Provisioned imported containers....done
  Starting instance...done
Done.
Instance [dev-box] has successfully been created.

See logs with:
gcloud beta run instances logs read dev-box --region europe-west4

Connect to the instance with:
gcloud beta run instances ssh dev-box --region europe-west4 --project YOUR_PROJECT_ID

Unlike Cloud Run services (where you pass --ssh at deploy time to opt in), Cloud Run instances enable SSH by default. Open a shell inside the instance dev-box:

gcloud beta run instances ssh dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID
Project: YOUR_PROJECT_ID
Region: europe-west4
Instance: dev-box
Revision: dev-box-wtyhh3s5y5
Container: worker
Image: mirror.gcr.io/library/ubuntu@sha256:a2d43bffc46670d7108bb3c0468c67c5557c4c92e83e1e34cbff1322ad1b94dc
root@localhost:/# uname -a
Linux localhost 6.6.137+ #1 SMP PREEMPT_DYNAMIC Thu Oct 15 09:05:57 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
root@localhost:/# exit

Cloud Run prints the instance metadata and drops you into a root@localhost shell inside the container. In the session above, running uname -a shows the microVM's Linux kernel (6.6.137+), and exit closes the SSH connection.

Closing the SSH session leaves the container running in the background. Stop the instance when you're not using it so you aren't billed for idle compute time:

gcloud beta run instances stop dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID
Stopping [dev-box]...done.
Stopped instance [dev-box].

Listing your instances now shows dev-box with a stopped icon (■):

gcloud beta run instances list --project=$PROJECT_ID
   INSTANCE  REGION        CREATED AT               CREATED BY
■  dev-box   europe-west4  2026-10-22 13:00:21 UTC  developer@example.com

When you need the environment again, start it back up:

gcloud beta run instances start dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID
Starting [dev-box]...done.
Started instance [dev-box].

Listing your instances again shows dev-box with a running icon (▶):

gcloud beta run instances list --project=$PROJECT_ID
   INSTANCE  REGION        CREATED AT               CREATED BY
▶  dev-box   europe-west4  2026-10-22 13:00:21 UTC  developer@example.com

Persisting files across restarts with a Cloud Storage bucket

Stopping a Cloud Run instance terminates its microVM. Everything written to the container's filesystem lives in memory and disappears when you run stop or restart. To keep project files across sessions, you can mount a Cloud Storage bucket as a local directory inside the container.

Mounting a bucket at /workspace

First, create a regional bucket in the same region as your instance (europe-west4), grant the roles/storage.objectUser IAM role (permission to read and write objects) on that bucket to the service account dev-box-sa, and update the instance dev-box to mount the bucket at the directory /workspace.

Create the Cloud Storage bucket:

gcloud storage buckets create gs://$PROJECT_ID-dev-box-workspace \
  --location=europe-west4 \
  --uniform-bucket-level-access \
  --project=$PROJECT_ID
Creating gs://YOUR_PROJECT_ID-dev-box-workspace/...
  • --location=europe-west4 creates the bucket in the same region as the instance to minimize network latency and avoid cross-region data transfer charges.
  • --uniform-bucket-level-access disables legacy per-object Access Control Lists (ACLs) so access is managed uniformly through IAM policies.

Grant the service account dev-box-sa permission to read and write objects in the bucket:

gcloud storage buckets add-iam-policy-binding gs://$PROJECT_ID-dev-box-workspace \
  --member="serviceAccount:dev-box-sa@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/storage.objectUser" \
  --project=$PROJECT_ID
bindings:
- members:
  - serviceAccount:dev-box-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
  role: roles/storage.objectUser

Now update the instance dev-box to attach the bucket as a cloud-storage volume mounted at the directory /workspace:

gcloud beta run instances update dev-box \
  --add-volume=name=workspace,type=cloud-storage,bucket=$PROJECT_ID-dev-box-workspace \
  --add-volume-mount=volume=workspace,mount-path=/workspace \
  --region=europe-west4 \
  --project=$PROJECT_ID
  • --add-volume registers a volume named workspace backed by the $PROJECT_ID-dev-box-workspace Cloud Storage bucket.
  • --add-volume-mount mounts the workspace volume into the container filesystem at the directory /workspace.

Updating the instance restarts it with the bucket mounted at the directory /workspace:

Updating Cloud Run instance [dev-box] in project [YOUR_PROJECT_ID] region [europe-west4]
Updating instance...
  Importing container... Imported container image in 1.06s....done
  Provisioning resources... Provisioned imported containers....done
  Starting instance...done
Done.
Instance [dev-box] has successfully been updated.

To verify what persists across a restart, connect to the instance dev-box over SSH and write one file to /tmp/session.txt and another to /workspace/persistent.txt:

gcloud beta run instances ssh dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID
Project: YOUR_PROJECT_ID
Region: europe-west4
Instance: dev-box
Revision: dev-box-9k4m2p8x1q
Container: worker
Image: mirror.gcr.io/library/ubuntu@sha256:a2d43bffc46670d7108bb3c0468c67c5557c4c92e83e1e34cbff1322ad1b94dc
root@localhost:/# echo "temp data" > /tmp/session.txt
root@localhost:/# echo "saved across restarts" > /workspace/persistent.txt
root@localhost:/# exit

Now restart the instance dev-box (which stops the current microVM and starts a new one) and reconnect over SSH:

gcloud beta run instances restart dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID
Stopping [dev-box]...done.
Starting [dev-box]...done.
Restarted instance [dev-box].
gcloud beta run instances ssh dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID
Project: YOUR_PROJECT_ID
Region: europe-west4
Instance: dev-box
Revision: dev-box-7r2n5v9c4m
Container: worker
Image: mirror.gcr.io/library/ubuntu@sha256:a2d43bffc46670d7108bb3c0468c67c5557c4c92e83e1e34cbff1322ad1b94dc
root@localhost:/# cat /tmp/session.txt
cat: /tmp/session.txt: No such file or directory
root@localhost:/# cat /workspace/persistent.txt
saved across restarts
root@localhost:/# exit

In the session above, notice that the SSH header reports a new revision ID (dev-box-7r2n5v9c4m instead of dev-box-9k4m2p8x1q) and /tmp/session.txt is gone because restarting the instance replaced the microVM and its in-memory root filesystem. Meanwhile, /workspace/persistent.txt remains intact in the mounted Cloud Storage bucket.

A note on file-based databases like SQLite

One thing to be aware of: some file-based databases, such as SQLite, start returning database is locked errors or suffer silent corruption when you store their files directly on a Cloud Storage mount like /workspace in this example.

While the mounted bucket looks like a normal directory inside your container, Cloud Run attaches it using Cloud Storage FUSE, a user-space object storage adapter rather than a POSIX block filesystem. Cloud Storage FUSE doesn't support POSIX byte-range file locking (fcntl or flock) and can't update individual database pages in place; modifying a small range of bytes re-uploads the entire object when the file handle closes. To avoid corruption, keep the active SQLite database file on the container's local in-memory filesystem (such as /tmp), restore it from the bucket on startup, and back it up to the bucket on shutdown, or use an external database.

Hosting a singleton web app

Some apps assume they're running as a single stateful process. Deploying them to a standard Cloud Run service can cause subtle bugs if the autoscaler spins up a second replica, or when it shuts down the last remaining instance.

A Cloud Run instance gives that workload a dedicated run.app HTTPS URL backed by exactly one container, and can run continuously for up to 7 days between automatic infrastructure restarts.

Create a web-demo instance running Python's built-in HTTP server on port 8080:

gcloud beta run instances create web-demo \
  --image=python:3.15-slim \
  --command=python3 \
  --args=-m,http.server,8080 \
  --port=8080 \
  --restart-policy=on-failure \
  --service-account=dev-box-sa@$PROJECT_ID.iam.gserviceaccount.com \
  --region=europe-west4 \
  --project=$PROJECT_ID
  • --port=8080 tells Cloud Run's ingress proxy which container port receives HTTP requests. Whenever an instance has a default URL enabled, Cloud Run also runs a default TCP startup probe against this port (waiting up to 240 seconds for the container to start listening) before routing HTTP or SSH traffic to the instance.
  • --restart-policy=on-failure (the default) restarts the container automatically up to three times if the process exits with a non-zero status code or fails its startup probe. You can also set --restart-policy=always to restart on any exit code, or --restart-policy=never to leave the instance stopped after a failure.

Because --default-url is enabled unless you pass --no-default-url, Cloud Run assigns an HTTPS URL and locks it down by default:

Done.
Instance [web-demo] has successfully been created.

See logs with:
gcloud beta run instances logs read web-demo --region europe-west4

URL: https://web-demo-123456789012.europe-west4.run.app

Proxy locally with:
gcloud beta run instances proxy web-demo --region europe-west4 --project YOUR_PROJECT_ID
To make this URL public, use gcloud beta run instances update web-demo --no-invoker-iam-check --region europe-west4

Testing privately with the local proxy

If you request the run.app URL without credentials right now, Google Frontend returns HTTP/2 403. To reach the instance privately from your laptop using your Google Cloud credentials, start the local proxy:

gcloud beta run instances proxy web-demo \
  --region=europe-west4 \
  --port=8888 \
  --project=$PROJECT_ID
Proxying to Cloud Run instance [web-demo] in project [YOUR_PROJECT_ID] region [europe-west4]
http://127.0.0.1:8888 proxies to https://web-demo-123456789012.europe-west4.run.app

Sending a request to http://localhost:8888 attaches your IAM token automatically and returns the directory listing from the Python container:

curl -i http://localhost:8888
HTTP/1.1 200 OK
Content-Length: 832
Content-Type: text/html; charset=utf-8
Server: Google Frontend

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>

Making the instance URL public

When you want to expose the singleton web app to the internet without requiring callers to present a Google Cloud IAM token, update the instance with --public:

gcloud beta run instances update web-demo \
  --public \
  --region=europe-west4 \
  --project=$PROJECT_ID
Updating Cloud Run instance [web-demo] in project [YOUR_PROJECT_ID] region [europe-west4]
Updating instance...done.
Done.
Instance [web-demo] has successfully been updated.

URL: https://web-demo-123456789012.europe-west4.run.app

Unauthenticated requests to the run.app URL now succeed directly:

curl -i https://web-demo-123456789012.europe-west4.run.app
HTTP/2 200
content-type: text/html; charset=utf-8
server: Google Frontend
content-length: 832

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Directory listing for /</title>
</head>

Regional availability, CPU bursting, and pricing

Before moving a workload into regular use, it helps to know which regions support Cloud Run instances, how the shared-CPU burst model works, and what an instance costs while running compared to when it's stopped.

Selecting a supported region

As of October 2026, Cloud Run instances are available in almost every Google Cloud region except the three oldest high-demand locations: europe-west1 (Belgium), us-central1 (Iowa), and us-east1 (South Carolina). You can check the latest regional rollout table in the Cloud Run locations documentation.

If you try to create an instance in an unsupported region such as europe-west1, gcloud CLI returns a REGION_CAPACITY_EXHAUSTED precondition error along with the full list of supported regions in the error metadata:

gcloud beta run instances create dev-box \
  --image=ubuntu:24.04 \
  --command=sleep \
  --args=infinity \
  --region=europe-west1 \
  --project=$PROJECT_ID
Creating Cloud Run instance [dev-box] in project [YOUR_PROJECT_ID] region [europe-west1]
Creating instance...failed
ERROR: (gcloud.beta.run.instances.create) FAILED_PRECONDITION: Instance capacity in region
europe-west1 is currently exhausted. Please pick a different region.
- '@type': type.googleapis.com/google.rpc.ErrorInfo
  domain: run.googleapis.com
  metadata:
    available_regions:
    africa-south1,asia-east1,asia-east2,asia-northeast1,asia-northeast2,asia-northeast3,asia-south1,asia-south2,asia-southeast1,asia-southeast2,asia-southeast3,asia-southeast4,australia-southeast1,australia-southeast2,europe-central2,europe-north1,europe-north2,europe-southwest1,europe-west10,europe-west12,europe-west15,europe-west2,europe-west3,europe-west4,europe-west6,europe-west8,europe-west9,me-central1,me-central2,me-west1,northamerica-northeast1,northamerica-northeast2,northamerica-south1,southamerica-east1,southamerica-west1,us-central2,us-east4,us-east5,us-east7,us-south1,us-west1,us-west2,us-west3,us-west4,us-west8
  reason: REGION_CAPACITY_EXHAUSTED

For European workloads, europe-west4 (Netherlands) supports Cloud Run instances. For US workloads, us-east4 (Northern Virginia) or us-west1 (Oregon) are good defaults.

Shared CPU bursting and cost estimates

A Cloud Run instance defaults to 2 vCPUs and 2 GiB of memory (--cpu=2 --memory=2Gi), with a minimum of 1 vCPU and 512 MiB of memory (--cpu=1 --memory=512Mi). You can configure an instance with 1, 2, 4, 6, or 8 vCPUs and up to 32Gi of memory.

Cloud Run instances use a shared CPU allocation model:

  • Each instance receives a continuous baseline of 6.25% (1/16th) of its configured vCPUs.
  • Whenever CPU usage sits below that 6.25% baseline, the instance accrues unused CPU time into a burst balance budget (up to 500 seconds, or about 8 minutes).
  • When the instance uses more than 6.25% CPU, it bursts up to 100% of its configured vCPUs until the burst balance is depleted, after which it throttles back to the 6.25% baseline until the budget replenishes.

Cloud Run bills instances only while they're running. When you stop an instance with gcloud beta run instances stop, compute billing drops to $0 while Cloud Run retains your instance configuration, IAM policy, and URL mapping. Using the Cloud Run instances pricing rates for europe-west4, us-east4, and us-west1 ($0.00000027 per vCPU-second and $0.00000193 per GiB-second):

  • Running the instance dev-box with the default 2 vCPUs and 2 GiB of memory for 2 hours a day across 20 workdays a month (144,000 seconds) and stopping it when you don't use it costs about $0.63 per month ($0.08 for CPU and $0.56 for memory).
  • Running the instance web-demo 24/7 for a 30-day month (2,592,000 seconds) with the minimum 1 vCPU and 512 MiB of memory (--cpu=1 --memory=512Mi) costs about $3.20 per month ($0.70 for CPU and $2.50 for memory), or about $11.40 per month with the default 2 vCPUs and 2 GiB of memory.

Cloud Run pricing is subject to change and these examples might contain mistakes, so check the Cloud Run pricing page and do your own math for your workloads.

Cleaning up

When you no longer need the test instances or their backing resources, delete the two instances, the Cloud Storage bucket, and the service account so no billable resources remain in your project.

First, delete the dev-box instance:

gcloud beta run instances delete dev-box \
  --region=europe-west4 \
  --project=$PROJECT_ID \
  --quiet

Next, delete the web-demo instance:

gcloud beta run instances delete web-demo \
  --region=europe-west4 \
  --project=$PROJECT_ID \
  --quiet

Remove the Cloud Storage bucket and all objects inside it:

gcloud storage rm --recursive gs://$PROJECT_ID-dev-box-workspace \
  --project=$PROJECT_ID

Finally, delete the dev-box-sa service account:

gcloud iam service-accounts delete dev-box-sa@$PROJECT_ID.iam.gserviceaccount.com \
  --project=$PROJECT_ID \
  --quiet

If you spin up a Cloud Run instance for a remote workstation or a stateful singleton app, I'd love to hear what you build with it.

Signature