So, you’ve built your NestJS app and now want to deploy it online, without spending any money or adding a credit card. In this blog, we’ll walk through a clear, step-by-step process to Dockerize your app and deploy it on Render for free.
Render’s free tier makes it easy to deploy Dockerized apps, while Docker ensures your project runs consistently everywhere. In this guide, we’ll:
- 🐳 Dockerize a NestJS app using
pnpm. - 🚀 Deploy it to Render in two different ways.
- 🔁 Add CI/CD for automatic deployments on every push to
main. - 🎁 Bonus: Keep your free Render app alive 24/7 using a Cloudflare Worker.
Let’s dive in! 🐳
Why Docker for NestJS?
Docker helps package your NestJS app with all its dependencies so it runs exactly the same in all environments.
Render supports two ways of deploying Docker apps:
From a Dockerfile → Render builds the image itself
From a prebuilt Docker image → You push your image to Docker Hub (or any registry), and Render pulls it
We’ll cover both options.
Step 1: Dockerizing the NestJS App
First, we need to containerize our application. If you don’t have Docker installed, to verify your app is running. If it works, you're ready for deployment! ✅
Step 2: Deploying to Render
Now that your NestJS app is Dockerized, let's get it deployed on Render. We have two options:
Option A: The Simple Way (Let Render Build the Image)
This is the easiest way:
- Push your code to GitHub/GitLab
- In Render Dashboard → New → Web Service
- Connect your repository
- Render will detect the
Dockerfileand build the image automatically
That's it! Render will now build your Docker image from the Dockerfile and deploy your app. Easy. 🎉
Option B: The CI/CD Way (Prebuilt Images with GitHub Actions)
This method gives you more control and enables automatic deployments.
- Build the Docker image locally
- Push it to Docker Hub
- Trigger Render to pull the new image
This also enables automatic CI/CD deployments on every push.
Step 1: Push to Docker Hub
# Build image
docker build -t nest-backend .
# Tag with Docker Hub username
docker tag nest-backend your-username/nest-backend:latest
# Push to Docker Hub
docker push your-username/nest-backend:latest
On Render, choose Deploy an existing Docker image and use:
docker.io/your-username/nest-backend:latest
Render will fetch the latest image whenever you trigger a redeploy.
📝 Notes on tags:
- Render redeploys based on the tag you specify (
latest,v1.0.0, etc.).
- Using
latestis simple, but versioned tags (e.g.,v1.0.0) are safer for production since they make rollbacks easier.
- Render only fetches a new image from Docker Hub when you trigger a redeploy (manually or via CI/CD).
Step 2: Automate with GitHub Actions
Create .github/workflows/docker-build.yml:
name: Build & Push Docker Image
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: your-username/nest-backend:latest
- name: Trigger Render Deploy
run: |
curl -X POST ${{ secrets.RENDER_DEPLOY_HOOK }}
In your GitHub repo → Settings → Secrets → add:
DOCKER_USERNAME→ your Docker Hub username
DOCKER_PASSWORD→ your Docker Hub access token
RENDER_DEPLOY_HOOK→ from Render dashboard (service → settings → deploy hook URL)
Now every push to main will:
- Build the Docker image
- Push it to Docker Hub
- Trigger a new Render deployment
🎁 Bonus: Keep Your Render App Alive 24/7
On Render’s free tier, your service goes to sleep after 15 minutes of inactivity to save resources. When that happens, the next request can feel slow because the app has to “cold start.”
To prevent this, you can set up a simple heartbeat that pings your app every few minutes.
You don’t have to use Cloudflare Workers — you could also use:
- Any external cron job service
In this tutorial, we’ll go with with Cloudflare Workers (free tier).
Create a Worker
Install Wrangler, Cloudflare’s CLI.
npm install -g wrangler
Generate a new worker:
wrangler init keep-alive-worker
Configure the Worker
In wrangler.toml:
name = "keep-alive-worker"
main = "src/index.ts"
compatibility_date = "2025-09-13"
# Add this
[triggers]
crons = ["*/15 * * * *"]
# (Optional) to enable logs for worker
[observability.logs]
enabled = true
Worker Code
In src/index.ts:
const SERVICES = [
'https://your-app-name.onrender.com', // Your app's URL
// Add more services here if needed!
];
export default {
async scheduled(event, env, ctx) {
for (const url of SERVICES) {
try {
const res = await fetch(url);
console.log(`✅ Pinged ${url} → ${res.status}`);
} catch (err) {
console.error(`❌ Failed to ping ${url}`, err);
}
}
},
};
Deploy the Worker
wrangler deploy
That’s it! 🎉 Your Cloudflare Worker will automatically ping your Render app(s) every 15 minutes, keeping them awake and responsive.
SOCIAL SHARE CARD GENERATOR