DEV Community

Cover image for How to Deploy a Dockerized Node.js App on Google Cloud Run
Arunangshu Das
Arunangshu Das

Posted on

How to Deploy a Dockerized Node.js App on Google Cloud Run

If you're building scalable applications in Node.js, there's a good chance you've considered Dockerizing your app to make it more portable and consistent across environments. But once it’s containerized, the next question becomes: where do I deploy this? That’s where Google Cloud Run comes in.

Google Cloud Run is a fully managed platform that lets you deploy containerized applications that scale automatically. It abstracts away infrastructure headaches, handles HTTP traffic, scales to zero when idle, and runs your app in a secure, isolated environment.

Why Use Google Cloud Run?

Before we dive into the technical details, let’s take a second to appreciate why Cloud Run is such a powerful option for modern web apps:

  • Serverless but flexible: It’s serverless, but you can bring your own Docker container.
  • Secure by default: HTTPS, traffic encryption, and IAM integration.
  • Pay-per-use: You only pay when your app is serving requests.
  • Fast scaling: Cloud Run scales from zero to thousands of requests in seconds.
  • Global deployment: Deploy close to your users with regional support.

What You’ll Build

In this tutorial, we’ll take a basic Node.js API, Dockerize it, and deploy it to Google Cloud Run.

The app will:

  • Listen on a specific port.
  • Respond with a simple JSON message.
  • Be containerized using Docker.
  • Be deployed via the Google Cloud CLI.

Prerequisites

To follow along, make sure you have:

  • A Google Cloud account (with billing enabled).
  • The gcloud CLI installed and configured.
  • Docker installed and running.
  • Basic knowledge of Node.js and Express.

Let’s go!


Step 1: Build a Simple Node.js App

Create a new folder for your project:

mkdir node-cloud-run
cd node-cloud-run
Enter fullscreen mode Exit fullscreen mode

Initialize your Node.js app:

npm init -y
Enter fullscreen mode Exit fullscreen mode

Install Express:

npm install express
Enter fullscreen mode Exit fullscreen mode

Create an index.js file:

// index.js
const express = require('express');
const app = express();
 
const PORT = process.env.PORT || 8080;
 
app.get('/', (req, res) => {
  res.json({ message: 'Hello from Cloud Run + Docker + Node.js!' });
});
 
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

Update package.json to include a start script:

"scripts": {
  "start": "node index.js"
}
Enter fullscreen mode Exit fullscreen mode

That's it — you now have a minimal Express API.


Step 2: Dockerize the App

Now let’s add a Dockerfile to containerize the app.

Create a Dockerfile:

# Use the official Node.js 18 image as a base
FROM node:18-slim
 
# Create app directory
WORKDIR /usr/src/app
 
# Copy package.json and install dependencies
COPY package*.json ./
RUN npm install --production
 
# Copy app files
COPY . .
 
# Expose the port Cloud Run expects
EXPOSE 8080
 
# Run the app
CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

Create a .dockerignore file to prevent unnecessary files from being added to the image:

node_modules
npm-debug.log
Enter fullscreen mode Exit fullscreen mode

Now you can build and run your container locally to test it:

docker build -t node-cloud-run .
docker run -p 8080:8080 node-cloud-run
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:8080 — you should see your JSON response.


Step 3: Set Up Google Cloud Project

Go to the Google Cloud Console and:

  1. Create a new project.
  2. Enable Cloud Run, Cloud Build, and Artifact Registry APIs.
  3. Link a billing account if not already linked.

Then authenticate with the CLI:

gcloud auth login
gcloud config set project [YOUR_PROJECT_ID]
Enter fullscreen mode Exit fullscreen mode

Replace [YOUR_PROJECT_ID] with your actual project ID.


Step 4: Push to Artifact Registry

You can either build the Docker image locally and push it or use Cloud Build to build it directly in the cloud. We’ll use Cloud Build here for simplicity.

First, enable Artifact Registry and create a new Docker repository:

gcloud artifacts repositories create my-docker-repo \
  --repository-format=docker \
  --location=us-central1
Enter fullscreen mode Exit fullscreen mode

Now tag your Docker image for the registry:

docker tag node-cloud-run us-central1-docker.pkg.dev/[PROJECT_ID]/my-docker-repo/node-cloud-run
Enter fullscreen mode Exit fullscreen mode

Push it to the Artifact Registry:

docker push us-central1-docker.pkg.dev/[PROJECT_ID]/my-docker-repo/node-cloud-run
Enter fullscreen mode Exit fullscreen mode

Alternatively, use Cloud Build to handle everything:

gcloud builds submit --tag us-central1-docker.pkg.dev/[PROJECT_ID]/my-docker-repo/node-cloud-run
Enter fullscreen mode Exit fullscreen mode

Step 5: Deploy to Google Cloud Run

Now that your image is in the registry, it’s time to deploy it!

gcloud run deploy node-cloud-run \
  --image us-central1-docker.pkg.dev/[PROJECT_ID]/my-docker-repo/node-cloud-run \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated
Enter fullscreen mode Exit fullscreen mode

The --allow-unauthenticated flag makes your service publicly accessible.

After a few moments, you’ll see a URL like:

Service [node-cloud-run] deployed to:
https://node-cloud-run-xyz.a.run.app
Enter fullscreen mode Exit fullscreen mode

Open the link — and boom! Your app is live on the internet


Step 6: CI/CD with Cloud Build (Optional but Recommended)

For production apps, you’ll want to automate this process.

You can create a cloudbuild.yaml file like this:

steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-docker-repo/node-cloud-run', '.']
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-docker-repo/node-cloud-run']
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    args: ['run', 'deploy', 'node-cloud-run', '--image', 'us-central1-docker.pkg.dev/$PROJECT_ID/my-docker-repo/node-cloud-run', '--region', 'us-central1', '--platform', 'managed', '--allow-unauthenticated']
Enter fullscreen mode Exit fullscreen mode

Then run:

gcloud builds submit --config cloudbuild.yaml
Enter fullscreen mode Exit fullscreen mode

This sets you up for CI/CD deployment every time you commit to your repo and push to Cloud Build.


Production Considerations

Here are a few things to consider before going live:

1. Health Checks

Use READINESS_CHECK_PATH and LIVENESS_CHECK_PATH if your app needs health verification.

2. Environment Variables

Cloud Run supports environment variables via:

gcloud run deploy ... --set-env-vars "NODE_ENV=production,API_KEY=yourkey"
Enter fullscreen mode Exit fullscreen mode

Or configure them in the Cloud Console UI.

3. CPU and Memory Allocation

The default might not be enough. You can configure:

--memory 512Mi --cpu 1
Enter fullscreen mode Exit fullscreen mode

4. Set Concurrency

By default, each container instance can handle multiple requests. You can change this:

--concurrency=1
Enter fullscreen mode Exit fullscreen mode

This is useful if your app isn’t thread-safe.

5. Authentication

Disable --allow-unauthenticated to restrict access and use IAM or Firebase Auth.


Troubleshooting Tips

Error: Port not bound correctly?

Cloud Run expects your app to listen on PORT from the environment. Use process.env.PORT.

Docker build fails?

Check .dockerignore — sometimes large node_modules folders or missing files cause issues.

Deployment is stuck or failing?

Use the gcloud run services describe [SERVICE_NAME] to check logs and settings.

App crashes on startup?

Enable logging and diagnostics in Cloud Console to debug further.


Summary

Major steps to deploying your Dockerized Node.js app on Google Cloud Run:

→ Build a simple Node.js Express app
→ Create a Dockerfile and containerize it
→ Push the image to Google Artifact Registry
→ Deploy the image to Cloud Run
→ Automate deployments with Cloud Build
→ Add production optimizations and environment variables
Google Cloud Run gives you the flexibility of containers with the convenience of serverless deployment. Whether you're building APIs, microservices, or full-stack apps, it's a fantastic choice to run your Dockerized Node.js application with minimal hassle.

You may also like:

  1. 10 Common Mistakes with Synchronous Code in Node.js

  2. Why 85% of Developers Use Express.js Wrongly

  3. Implementing Zero-Downtime Deployments in Node.js

  4. 10 Common Memory Management Mistakes in Node.js

  5. 5 Key Differences Between ^ and ~ in package.json

  6. Scaling Node.js for Robust Multi-Tenant Architectures

  7. 6 Common Mistakes in Domain-Driven Design (DDD) with Express.js

  8. 10 Performance Enhancements in Node.js Using V8

  9. Can Node.js Handle Millions of Users?

  10. Express.js Secrets That Senior Developers Don’t Share
    Read more blogs from Here

Share your experiences in the comments, and let’s discuss how to tackle them!

Follow me on Linkedin

Top comments (0)