Deploying a Next.js Application to Google Cloud Run

Deploying a Next.js Application to Google Cloud Run

Google Cloud Run is a serverless platform for deploying containerized applications with automatic scaling and built-in HTTPS. I use it to deploy Next.js applications with Docker and automate deployments using Google Cloud Build for a reliable CI/CD workflow.

• DevOps & CI/CD• Web Development
Written byRobert
7 min read
Tags:
DeploymentCloud ComputingFree Tier

Overview

Google Cloud Run provides a fully managed serverless platform for deploying containerized applications without managing infrastructure. By combining Docker, Cloud Run, and Cloud Build, you can automate deployments, enable continuous integration, and scale your Next.js application based on demand.

This guide demonstrates how to containerize a Next.js application, deploy it to Cloud Run, and configure an automated CI/CD pipeline using GitHub and Google Cloud Build.

Why Google Cloud Run?

Google Cloud Run is an excellent deployment platform for modern web applications because it removes the complexity of managing servers while providing reliable performance and automatic scaling.

Key Benefits

  • Fully managed serverless hosting
  • Automatic scaling based on traffic
  • Container-based deployments with Docker
  • Continuous deployment using Cloud Build
  • Pay only for resources consumed
  • Built-in HTTPS and secure networking
  • Easy integration with GitHub

Prerequisites

Before deployment, make sure you have:

  • A Google Cloud project
  • Billing enabled
  • A Next.js application
  • Docker installed
  • A GitHub repository
  • Google Cloud CLI (optional for local deployments)

Configure Your Google Cloud Project

Create a new Google Cloud project or select an existing one.

Enable the required services:

  • Cloud Run API
  • Cloud Build API
  • Artifact Registry (or Container Registry)
  • Cloud Logging API (optional)

These services provide the infrastructure needed to build, store, and deploy your application.

Prepare Your Next.js Application

Containerize your application by creating a Dockerfile in the project root.

The Dockerfile defines:

  • Base image
  • Dependency installation
  • Application build
  • Production startup
Dockerfile
# Step 1: Base Image
FROM node:23.0.0-alpine3.20 AS base

# Install compatibility package
RUN apk add --no-cache libc6-compat

# Set working directory
WORKDIR /app

# Step 2: Dependencies Layer
FROM base AS deps

COPY package*.json ./

# Install dependencies
RUN npm ci

# Step 3: Build Layer
FROM base AS builder

WORKDIR /app

# Copy dependencies from previous layer
COPY --from=deps /app/node_modules ./node_modules

# Copy the rest of the app files
COPY . .

# Disable Next.js telemetry
ENV NEXT_TELEMETRY_DISABLED 1

# Build the Next.js application
RUN npm run build

# Step 4: Runner Layer
FROM base AS runner

WORKDIR /app

# Set environment to production
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
ENV PORT 3000  # Use port 3000 as per your Cloud Run setup

# Create non-root user and group
RUN addgroup --system --gid 1001 nodejs \
    && adduser --system --uid 1001 nextjs

# Copy necessary files for runtime
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

# Switch to non-root user
USER nextjs

# Expose port 3000
EXPOSE 3000

# Start the application
CMD ["npm", "start"]

Test the Container (Optional)

Before deploying, build and run the container locally to verify that everything works correctly.

Bash
# 1. Build the Docker image from your Dockerfile
docker build -t nextjs-app .

# 2. Run the container and map the ports
docker run -p 3000:3000 nextjs-app

Deploy to Google Cloud Run

Open the Cloud Run service in the Google Cloud Console and create a new service.

Configure the deployment using:

  • Container image
  • Deployment region
  • Service name
  • Public accessibility
  • Port configuration (3000)

Enable unauthenticated access if the application should be publicly accessible.

Once deployment is complete, Cloud Run generates a public HTTPS endpoint for your application.

Create Service
Set up with Cloud Build

Configure Service Settings

Before finalizing the deployment, review the service configuration.

Recommended settings include:

  • Port: 3000
  • Automatic scaling enabled
  • Maximum instances based on expected traffic
  • Appropriate CPU and memory allocation
  • Environment variables (if required)

These settings help optimize performance while controlling operational costs.

Configure CI/CD with Google Cloud Build

To automate future deployments, configure Google Cloud Build to build and deploy the application whenever new code is pushed to GitHub.

Create a cloudbuild.yaml file in the project root that defines the build and deployment pipeline.

cloudbuild
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: my-service
  namespace: 'MY_PROJECT_NAMESPACE'
  selfLink: /apis/serving.knative.dev/v1/namespaces/MY_PROJECT_NAMESPACE/services/my-service
  uid: unique-id-placeholder
  resourceVersion: version-placeholder
  generation: 1
  creationTimestamp: '2024-11-12T00:00:00.000000Z'
  labels:
    commit-sha: placeholder-sha
    gcb-build-id: build-id-placeholder
    gcb-trigger-id: trigger-id-placeholder
    gcb-trigger-region: global
    managed-by: cloud-build-deploy-cloud-run
    cloud.googleapis.com/location: us-central1
  annotations:
    serving.knative.dev/creator: user@example.com
    serving.knative.dev/lastModifier: project-id-compute@developer.gserviceaccount.com
    run.googleapis.com/client-name: gcloud
    run.googleapis.com/client-version: placeholder-version
    run.googleapis.com/operation-id: operation-id-placeholder
    run.googleapis.com/ingress: all
    run.googleapis.com/ingress-status: all
    run.googleapis.com/urls: >-
      ["https://my-service-MY_PROJECT_NAMESPACE.us-central1.run.app","https://my-service-unique-id-placeholder.a.run.app"]
spec:
  template:
    metadata:
      labels:
        client.knative.dev/nonce: nonce-placeholder
        commit-sha: placeholder-sha
        gcb-build-id: build-id-placeholder
        gcb-trigger-id: trigger-id-placeholder
        gcb-trigger-region: global
        managed-by: cloud-build-deploy-cloud-run
        run.googleapis.com/startupProbeType: Default
      annotations:
        autoscaling.knative.dev/maxScale: '10'
        run.googleapis.com/client-name: gcloud
        run.googleapis.com/client-version: placeholder-version
        run.googleapis.com/startup-cpu-boost: 'true'
    spec:
      containerConcurrency: 80
      timeoutSeconds: 300
      serviceAccountName: project-id-compute@developer.gserviceaccount.com
      containers:
      - name: main-container
        image: >-
          us-central1-docker.pkg.dev/my-project/cloud-run-source-deploy/my-service/image:placeholder-sha
        ports:
        - name: http1
          containerPort: 3000
        env:
        - name: NEXT_PUBLIC_SANITY_PROJECT_ID
          value: my-sanity-project
        - name: NEXT_PUBLIC_SANITY_DATASET
          value: production
        - name: RESEND_API_KEY
          value: placeholder-key
        resources:
          limits:
            cpu: 1000m
            memory: 512Mi
        startupProbe:
          timeoutSeconds: 240
          periodSeconds: 240
          failureThreshold: 1
          tcpSocket:
            port: 3000
  traffic:
  - percent: 100
    latestRevision: true

Create a Build Trigger

Navigate to:

Cloud Build → Triggers

Create a new trigger and connect your GitHub repository.

Configure:

  • Repository
  • Deployment branch
  • Trigger event
  • Build configuration using cloudbuild.yaml

From this point forward, every push to the selected branch automatically starts a new deployment.

[Image: Cloud Build Trigger]

Verify the Deployment

Commit and push your latest changes to GitHub.

Google Cloud Build automatically:

  1. Clones the repository
  2. Builds the Docker image
  3. Pushes the container image
  4. Deploys the latest version to Cloud Run

Monitor deployment progress from Cloud Build → History and verify that the updated application is live.

Conclusion

Google Cloud Run offers a modern and efficient deployment workflow for Next.js applications by combining serverless infrastructure with containerized deployments. When paired with Docker and Google Cloud Build, it provides automated CI/CD, seamless scaling, and reliable production deployments with minimal operational overhead.

For freelance and production projects, I frequently recommend Google Cloud Run because it enables fast deployments, reduces infrastructure management, and automatically scales applications as traffic grows.

More Projects

Explore more projects related to this topic.