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
Initialize your Node.js app:
npm init -y
Install Express:
npm install express
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}`);
});
Update package.json
to include a start script:
"scripts": {
"start": "node index.js"
}
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"]
Create a .dockerignore
file to prevent unnecessary files from being added to the image:
node_modules
npm-debug.log
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
Visit http://localhost:8080
— you should see your JSON response.
Step 3: Set Up Google Cloud Project
Go to the Google Cloud Console and:
- Create a new project.
- Enable Cloud Run, Cloud Build, and Artifact Registry APIs.
- Link a billing account if not already linked.
Then authenticate with the CLI:
gcloud auth login
gcloud config set project [YOUR_PROJECT_ID]
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
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
Push it to the Artifact Registry:
docker push us-central1-docker.pkg.dev/[PROJECT_ID]/my-docker-repo/node-cloud-run
Alternatively, use Cloud Build to handle everything:
gcloud builds submit --tag us-central1-docker.pkg.dev/[PROJECT_ID]/my-docker-repo/node-cloud-run
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
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
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']
Then run:
gcloud builds submit --config cloudbuild.yaml
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"
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
4. Set Concurrency
By default, each container instance can handle multiple requests. You can change this:
--concurrency=1
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:
6 Common Mistakes in Domain-Driven Design (DDD) with Express.js
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)