---
title: How to migrate from Google Cloud Run to Vercel
description: Migrate from Cloud Run to Vercel by copying your Dockerfile to Dockerfile.vercel, aligning the PORT contract, moving secrets, and mapping jobs to cron.
url: /kb/guide/migrate-cloud-run-to-vercel
canonical_url: "https://vercel.com/kb/guide/migrate-cloud-run-to-vercel"
published: 2026-08-11
last_updated: 2026-08-11
authors: Ben Sabic
related:
  - /docs/functions/container-images
  - /docs/frameworks/more-frameworks
  - /docs/cron-jobs
  - /docs/container-registry
  - /docs/services
  - /kb/guide/migrate-fly-io-to-vercel
  - /kb/guide/migrate-railway-to-vercel
  - /kb/guide/migrate-render-to-vercel
  - /kb/guide/does-vercel-support-docker-deployments
  - /kb/guide/migrate-ghcr-to-vcr
  - /blog/dockerfile-on-vercel
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

To migrate from Google Cloud Run to Vercel, copy your Dockerfile to `Dockerfile.vercel` at the project root and deploy. Vercel detects the file, builds the image, pushes it to Vercel Container Registry, and routes all traffic to your container, which runs as a [Vercel Function on Fluid compute](https://vercel.com/docs/functions/container-images). The rest of the migration is contract alignment: the listening port, secrets, shutdown handling, and scheduled work.

This guide covers whether your service is a fit, how Cloud Run concepts map to Vercel, the migration steps, and what doesn't carry over.

## Should your app move?

Cloud Run services are the closest analog to Vercel's container model: both run stateless HTTP containers that scale to zero. If your service already lives inside that contract, the move is mostly mechanical, and you run it with less Google Cloud surface area to operate: no Artifact Registry repositories, IAM bindings, or Cloud Build triggers to maintain.

A service is a good fit when it:

- Serves HTTP requests and keeps no state between them
  
- Already tolerates scaling to zero, with no min-instances dependency
  
- Treats the filesystem as scratch space, which Cloud Run enforces anyway with its in-memory filesystem
  
- Runs scheduled work over HTTP rather than as long batch processes
  

It's a poor fit when it depends on Cloud Run jobs for long run-to-completion batch work, on warm instances held by min-instances, on GPUs, or on fixed egress IPs, since Secure Compute and Static IPs aren't yet supported with custom container images. If you're still deciding where a given workload belongs, the guide to [matching your Docker workload to a platform](https://vercel.com/i/which-platform-should-host-your-docker-app) walks through the decision.

## How do Cloud Run concepts map to Vercel?

| Cloud Run                                                                   | Vercel                                                                                               |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Service (stateless HTTP container, scales to zero by default)               | Container image running as a Vercel Function on Fluid compute                                        |
| Artifact Registry (`LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG`) | Vercel Container Registry (`vcr.vercel.com/team-slug/project-slug/my-repository:tag`)                |
| `gcloud run deploy SERVICE --image IMAGE_URL`                               | `vercel deploy`, or push to a connected Git repository                                               |
| `PORT` env var injected into the container, default `8080`                  | HTTP server on port `80` by default; override with a `PORT` environment variable in project settings |
| Secret Manager secrets as env vars or mounted volumes                       | Sensitive environment variables in project settings                                                  |
| Cloud Run jobs                                                              | Cron jobs sending an HTTP GET to an endpoint in your service                                         |
| `SIGTERM`, then `SIGKILL` after 10 seconds                                  | `SIGTERM` with a 30-second grace period before forced termination                                    |
| Source deploys (`gcloud run deploy` without `--image`, Cloud Build)         | Framework detection for Express, FastAPI, Flask, Django, Go, Next.js, and more                       |

TLS looks the same from inside the container: Cloud Run terminates TLS and proxies plain HTTP, and Vercel expects a plain HTTP server too.

## Migrate a Cloud Run service in 7 steps

### 1\. Copy your Dockerfile to Dockerfile.vercel

Place a `Dockerfile.vercel` (or `Containerfile.vercel`) at the root of your project. Vercel auto-detects it, adds a rewrite that routes all traffic to the container image, and builds and pushes the image during the build step. The Dockerfile you already deploy to Cloud Run is the starting point; the contract differences are the port and the shutdown timing, handled below.

If your service deployed from source on Cloud Run (running `gcloud run deploy` without `--image`), you may not need a Dockerfile at all. Vercel's [framework detection](https://vercel.com/docs/frameworks/more-frameworks) deploys Express, FastAPI, Flask, Django, Go, Next.js, and many other frameworks with minimal configuration.

### 2\. Set the port

Cloud Run injects a `PORT` environment variable, `8080` by default, and requires your server to listen on `0.0.0.0`. Vercel expects the container to open an HTTP server on port `80` by default, and you can override that by setting a `PORT` environment variable in project settings. If your code already reads `PORT` at startup, set the variable to `8080` in project settings and it runs unchanged.

### 3\. Move Secret Manager secrets to environment variables

Cloud Run exposes Secret Manager secrets as environment variables resolved at instance startup, or as mounted volumes fetched on read, wired with flags like `--set-secrets=ENV_VAR_NAME=SECRET_NAME:VERSION`. On Vercel, recreate each one as a sensitive environment variable in project settings. Google recommends pinning secrets to a version rather than `latest`, so copy the value of the pinned version you serve today. Secrets your code reads from a volume path need a code change to read from the environment instead; there are no mounted volumes on Vercel.

### 4\. Update shutdown handling

Both platforms send `SIGTERM` before stopping an instance. Cloud Run starts a 10-second period before `SIGKILL`; Vercel gives a 30-second grace period before forced termination. A shutdown handler written for Cloud Run gains time rather than losing it, but the period is fixed, so cleanup that can't finish in 30 seconds still needs to move out of the shutdown path. Scale-in triggers after 5 minutes without traffic in production, and after 30 seconds in preview deployments.

### 5\. Replace Cloud Run jobs with cron jobs

Cloud Run jobs run tasks to completion, must not listen on a port, and exit 0 on success. Vercel has no run-to-completion container equivalent, so scheduled jobs change shape: expose the task as an HTTP endpoint in your service, then add the schedule and path to `vercel.json` as a [cron job](https://vercel.com/docs/cron-jobs). Vercel triggers each run with an HTTP GET request to the configured `path` on the production deployment. Requests carry the `vercel-cron/1.0` user agent and an `x-vercel-cron-schedule` header, and schedules always run in UTC. Batch tasks that exceed Vercel's function duration limits should stay on Cloud Run.

### 6\. Test locally with vercel dev

Run `vercel dev` to start the container on your machine. It requires the `docker` CLI and a running Docker daemon. Confirm the port change here: the server should come up on the port you configured. You can also send your process a termination signal yourself to exercise the shutdown handler before deploying.

### 7\. Deploy and cut over

Deploy with `vercel deploy` or by pushing to a connected Git repository; every push gets a preview deployment, so you can test the migrated service on a real URL before production. During the build, the image is pushed to [Vercel Container Registry](https://vercel.com/docs/container-registry), a Docker-compatible registry at `vcr.vercel.com` with repositories private by default. Pushed images are optimized into a precompiled snapshot format that reduces startup time on Fluid compute. Once the preview checks out, ship it to production and point your domain at Vercel.

## What doesn't map from Cloud Run

- Cloud Run jobs. There is no run-to-completion container on Vercel: scheduled work becomes cron jobs invoking HTTP endpoints, and batch tasks longer than function duration limits should stay on Cloud Run.
  
- Min instances. Vercel's container docs define no setting that holds instances warm; scale-down after idle is automatic. The precompiled snapshot format reduces startup time instead.
  
- Persistent and mounted volumes. Cloud Run's filesystem is in-memory and non-persistent, so most services lose nothing here, but any volume mounts, including secret volumes, must become environment variables or external storage. Databases and caches are available through the Vercel Marketplace.
  
- Fixed egress IPs. Secure Compute and Static IPs aren't yet supported with custom container images. If a downstream system allowlists your Cloud Run egress, plan a different access path before cutting over.
  
- The 10-second shutdown window. It becomes 30 seconds on Vercel: more room, but fixed.
  
- Sidecar containers. Cloud Run can run additional containers next to the ingress container in one instance. On Vercel, a function runs the single image built from its Dockerfile, so fold sidecar work such as proxies or log forwarding into the main image, or split it into its own [service](https://vercel.com/docs/services) with its own `Dockerfile.vercel` in the same project, routed by rewrites.
  

## Frequently asked questions

### Does Vercel run my container the way Cloud Run does?

Mostly, yes. Cloud Run and Vercel both run stateless containers that serve HTTP and scale to zero, so the runtime contract carries over. The differences are details: Vercel expects your server on port 80 unless you set a PORT environment variable in project settings (Cloud Run defaults to 8080), the SIGTERM grace period is 30 seconds instead of 10, and standard Vercel Functions limits on size, memory, and duration apply.

### What replaces min instances on Vercel?

Nothing does. Vercel's container docs define no setting that holds instances warm: a production function scales down after 5 minutes without traffic, and a preview deployment after 30 seconds. Vercel instead optimizes pushed images into a precompiled snapshot format to reduce startup time on Fluid compute.

### What happens to my Cloud Run jobs?

Cloud Run jobs need a new shape, because Vercel has no run-to-completion container equivalent. Scheduled work becomes a Vercel cron job: an HTTP endpoint in your service that Vercel calls with a GET request on a schedule you define in vercel.json, always in UTC. Batch tasks that run longer than Vercel's function duration limits should stay on Cloud Run.

### Can I keep my images in Artifact Registry?

You can keep images in Artifact Registry for other consumers, but the image Vercel serves lives in Vercel Container Registry: the build step builds your Dockerfile.vercel and pushes the result to VCR automatically. VCR is Docker-compatible, so if you want existing images copied over, docker buildx imagetools create moves multi-platform images without pulling layers locally, and repositories are private by default.

### How do Secret Manager secrets move to Vercel?

Each secret becomes a sensitive environment variable in Vercel's project settings, which matches how Cloud Run exposes Secret Manager secrets as environment variables resolved at instance startup. Secrets your code reads from a mounted volume need a small code change to read from the environment instead, because Vercel functions have no mounted volumes.

## Related resources

- Migrate to Vercel from [Fly.io](https://vercel.com/kb/guide/migrate-fly-io-to-vercel), [Railway](https://vercel.com/kb/guide/migrate-railway-to-vercel), or [Render](https://vercel.com/kb/guide/migrate-render-to-vercel)
  
- [Does Vercel support Docker deployments?](https://vercel.com/kb/guide/does-vercel-support-docker-deployments)
  
- [How do I migrate images from GHCR to VCR?](https://vercel.com/kb/guide/migrate-ghcr-to-vcr)
  
- [Run any Dockerfile on Vercel](https://vercel.com/blog/dockerfile-on-vercel)
  
- [7 ways to use Docker containers on Vercel](https://vercel.com/i/7-ways-to-use-docker-containers-on-vercel)
  
- [Cloud Run container runtime contract](https://docs.cloud.google.com/run/docs/container-contract)