Deploying a Vite React App to Google Cloud Run (Step-by-Step)

A production-tested walkthrough for shipping a Vite + React single-page app to Google Cloud Run with Cloud Build, Nginx, and sensible caching headers.

TThe NAAO Technologies Team April 1, 2026 2 min read

Why Cloud Run for a static SPA?

Cloud Run isn't only for containerized backend APIs. For a marketing site or a lightweight SPA, it's a surprisingly clean fit: you get free TLS, custom domains, autoscaling to zero, and regional failover without ever touching a Kubernetes cluster. At our typical traffic volume, the bill rounds to zero.

This is the exact workflow we use on our own naaocreations.com site, and it's the same one we hand to early-stage clients who need to go live tomorrow.

The stack

  • Vite + React for the app
  • Nginx (alpine) to serve the built assets
  • Cloud Build for CI from main
  • Cloud Run for hosting
  • Artifact Registry for the container image

Dockerfile

A two-stage build keeps the final image small — about 25 MB for most SPAs:

FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]

Cloud Run listens on the PORT env var (defaults to 8080), so the Nginx listen 8080; directive matters.

nginx.conf

Serve / from index.html, cache static assets aggressively, don't cache HTML:

server {
  listen 8080;
  root /usr/share/nginx/html;
  index index.html;
  gzip on;
  gzip_types text/plain text/css application/javascript application/json;

  location / { try_files $uri $uri/ /index.html; }

  location ~* \.(js|css|svg|png|woff2|ico)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
  }
  location ~* \.html$ {
    expires -1;
    add_header Cache-Control "no-store";
  }
}

cloudbuild.yaml

steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/apps/naao-site:$SHORT_SHA', '.']
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/apps/naao-site:$SHORT_SHA']
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - run
      - deploy
      - naao-site
      - --image=us-central1-docker.pkg.dev/$PROJECT_ID/apps/naao-site:$SHORT_SHA
      - --region=us-central1
      - --allow-unauthenticated
      - --platform=managed
      - --cpu=1
      - --memory=256Mi
      - --min-instances=0
      - --max-instances=5

Gotchas we hit

  1. Port mismatch. Cloud Run injects PORT. If your Nginx listens on 80, you'll get 500s. Listen on 8080 explicitly (or templatize with envsubst).
  2. SPA 404s on deep links are always Nginx misconfig. The try_files ... /index.html fallback is mandatory.
  3. Min-instances = 0 causes cold starts (~200 ms with Nginx). For a marketing site, this is fine. For a real app, set it to 1.
  4. Environment variables injected at build time must be baked into the bundle with VITE_ prefix. Anything secret stays server-side.

Cost

For our traffic, GCP bills < $1/month. Cloud Build's first 120 build-minutes/day are free, and Cloud Run's free tier covers the invocations.

Next steps

Most of our sites evolve from pure SPA to SSG once we need SEO. If you're headed that direction, see our follow-up on swapping vite build for vite-react-ssg build — the Docker and Cloud Run pieces don't change.

Need help shipping your own app to production? Talk to our team.

Need help with this?

Our team ships this exact work for clients every week.

We cover Cloud Solutions, and Web Applications. Cloud-native deployments on GCP and AWS.

Related reading

NAAO Technologies

A NAAO Creations company

We specialize in building cutting-edge web and mobile applications for startups and enterprises, from Dexter, Michigan.

  • info@naaocreations.com
  • Dexter, Michigan

Engineering newsletter

Practical articles on shipping apps, AI, and cloud. One email, every couple of weeks. No spam.

© 2026 NAAO Creations. All rights reserved.