Skip to main content

Develop, test & deploy on Cloud Run

Exam guide§2.1

Before an app goes live on Cloud Run there is a short arc: decide whether it fits, turn source into a running container, honor the runtime contract, pick an execution environment, reach your data, and test it locally. This page walks that arc. The runtime states a container passes through (starting, idle, shutting down) are on Cloud Run container lifecycle.

Is your app a good fit for Cloud Run?

NumbersFit checklist - every criterion must be true
  • Serves requests, streams, or events over HTTP, HTTP/2, WebSockets, or gRPC - or runs to completion as a job.
  • Needs no local persistent disk - a local ephemeral (in-memory) or network file system is enough.
  • Is built to run as multiple instances simultaneously (stateless, horizontally scalable).
  • Needs at most 8 CPU and 32 GiB memory per instance.
  • Is containerized, or written in Go, Java, Node.js, Python, or .NET (so it can be containerized for you), or you can otherwise containerize it.
GotchaAll of the criteria, not any

An app is a good fit only if it meets every criterion. The 8 CPU / 32 GiB ceiling and the no persistent local disk rule are the two that most often disqualify an otherwise-portable app.

From source to a running service

Two paths get your code to a running service, and both end at a container Cloud Run runs:

  • Container path - you build and package the image yourself (any language), push it to Artifact Registry, then deploy. This is the deploy loop on the section overview.
  • Source-based path - skip the Dockerfile. Deploy your source and let Cloud Run build the image for you with Buildpacks.
</>Source codeBuildpacksContainer imageCloud Run service
Source-based deploy: with no Dockerfile, Cloud Run uses Buildpacks to build your source into a container image and deploy it - build and deploy are a single `gcloud run deploy --source` step.

Source-based deploy supports Go, Node.js, Python, Java, .NET Core, and Ruby. If a Dockerfile is present it is used; if not, Buildpacks packages your app and its dependencies into a container image.

GotchaBuilding a container image is optional

You never have to write a Dockerfile. gcloud run deploy --source (or the equivalent in Cloud Code) hands your source to Buildpacks, which produces the image and deploys it in one step.

Container runtime contract

Whatever language or base image you use, the container must honor Cloud Run's runtime contract. Executables must be compiled for Linux 64-bit; images may be Docker Image Manifest V2 (schema 1 or 2) or OCI format.

NumbersService contract
  • Listen for requests on the correct port - default 8080, configurable via $PORT.
  • Send a response within the request timeout (max 1 hour), including container startup time, or the request ends with a 504.
  • Do not implement TLS yourself.
NumbersJob contract
  • Exit with code 0 on success, a non-zero exit code on failure.
  • Do not listen on a port or start a web server - jobs do not serve requests.
GotchaCloud Run terminates TLS for you

Never implement transport-layer security in your container. Cloud Run terminates TLS for HTTPS and gRPC, then proxies plain HTTP/1 or gRPC to your container. For HTTP/2, handle requests in HTTP/2 cleartext (h2c).

Execution environments

Cloud Run runs services and jobs in one of two execution environments. Services default to first generation and can be switched; jobs always use second generation and cannot be changed.

First generationSecond generation
Default forServices (changeable)Jobs (cannot be changed)
Cold startFaster - shorter cold startsSlower cold starts
Linux compatibilityEmulates most, but not all, system callsFull Linux - all syscalls, namespaces, cgroups
Network file systemNot supportedSupported (required for NFS / Filestore)
CPU & networkStandardFaster CPU, faster network under packet loss
Best whenScale out fast, spiky or infrequent traffic, < 512 MiB memorySteady traffic, CPU-intensive work, NFS needed, or gen-1 syscall gaps
GotchaSecond generation is required for network file systems

To mount a network file system (Filestore, or Cloud Storage via Cloud Storage FUSE) on a service, you must deploy it in the second generation environment. Jobs already run on gen 2.

File system and data storage access

ContainerClient libraryApplication codeIn-memory file systemephemeralpersistentCloud data storageCloud StorageMemorystoreCloud SQLFilestoreFirestoreBigQuerySpanner
A Cloud Run container writes to a writable in-memory (ephemeral) file system that vanishes when the instance stops. For data that must persist, connect to Google Cloud data storage services.

Every container gets a writable in-memory file system. Writes consume the instance's allocated memory and do not persist past the instance - treat it as a per-request cache or scratch space, not storage.

For durable data:

  • Standard file semantics - use Filestore or another self-managed network file system, which needs the second generation environment. Cloud Storage FUSE mounts a bucket as a file system.
  • No file system needed (simplest) - use cloud data storage client libraries to talk directly to Firestore, Cloud SQL, Spanner, Cloud Storage, Memorystore, and BigQuery.
NumbersIn-memory file system facts
  • Writable, backed by the instance's allocated memory.
  • Not persisted - data is gone when the instance stops.
  • Default 512 MiB memory per instance (writes count against it); configurable up to 32 GiB.

Local development and testing

Run and test the container on your machine before deploying. Three options:

Cloud Code

Cloud Code is a set of IDE plugins for building, deploying, and integrating apps with Google Cloud.

FactsWhat Cloud Code gives you
  • Plugins for VS Code, IntelliJ, and Cloud Shell.
  • Create and deploy Kubernetes and Cloud Run apps from sample templates.
  • Run and debug locally in a Cloud Run emulator (configure CPU/memory, env vars, Cloud SQL connections).
  • Log streaming and viewing.

Local testing options

Cloud Codegcloud CLIDocker
HowCloud Run emulator inside your IDELocal dev environment that emulates Cloud Rundocker run the image locally
Builds withThe emulatorDockerfile if present, else BuildpacksYour Dockerfile
Auto-rebuild on changeYesYesNo
Test URLURL shown in IDE outputhttp://localhost:8080/http://localhost:<PORT>/
Best forIDE-integrated run + debugCLI workflowYou already use Docker

Recap

NumbersNumbers to remember
  • Resource ceiling: 8 CPU, 32 GiB memory per instance.
  • Default port: 8080 (configurable via $PORT).
  • Request timeout: up to 1 hour, else a 504.
  • Job result: exit 0 = success, non-zero = failure.
  • Network file system (Filestore / Cloud Storage FUSE) requires the second generation environment.
DECISIONContainer image or source-based deploy?

Build the image yourself when you need a specific base image or full control of the build. Choose source-based (--source, Buildpacks) when you want Cloud Run to build and deploy from source in one step - supported for Go, Node.js, Python, Java, .NET Core, and Ruby.

Pick this when: Dockerfile or full control over the build = build the image yourself; no Dockerfile, let Google build it = source-based with Buildpacks