Setting Up CI/CD for Next.js on GCP with Cloud Build
Setting Up CI/CD for Next.js on GCP with Cloud Build
In this tutorial, I'll show you how to set up a complete CI/CD pipeline for a Next.js application using Google Cloud Build and Firebase Hosting.
Why GCP?
Google Cloud Platform offers several advantages for hosting modern web applications:
- Free tier for personal projects
- Global CDN through Firebase Hosting
- Automatic SSL certificates
- Fast build times with Cloud Build
- Integrated ecosystem for future backend services
Prerequisites
Before we begin, make sure you have:
- A Google Cloud Platform account
- A GitHub repository with your Next.js app
- GCP CLI (
gcloud) installed locally
Step 1: Set Up Firebase Project
First, let's initialize Firebase in your project:
# Install Firebase CLI
npm install -g firebase-tools
# Login to Firebase
firebase login
# Initialize Firebase in your project
firebase init hosting
Select these options:
- Use existing project or create a new one
- Set public directory to
out(for Next.js static export) - Configure as single-page app: Yes
- Set up automatic builds with GitHub: No (we'll use Cloud Build)
Step 2: Configure Next.js for Static Export
Update your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true, // Required for static export
},
};
module.exports = nextConfig;
Step 3: Create Cloud Build Configuration
Create a cloudbuild.yaml file in your project root:
steps:
# Install dependencies
- name: 'node:18'
entrypoint: npm
args: ['install']
# Build the application
- name: 'node:18'
entrypoint: npm
args: ['run', 'build']
# Deploy to Firebase Hosting
- name: 'gcr.io/PROJECT_ID/firebase'
args: ['deploy', '--only', 'hosting', '--project', 'PROJECT_ID']
timeout: '1200s'
Replace PROJECT_ID with your actual GCP project ID in the cloudbuild.yaml file.
Step 4: Set Up GitHub Trigger
Now let's connect Cloud Build to your GitHub repository:
# Enable required APIs
gcloud services enable cloudbuild.googleapis.com
gcloud services enable firebase.googleapis.com
# Create a build trigger
gcloud builds triggers create github \
--repo-name=YOUR_REPO_NAME \
--repo-owner=YOUR_GITHUB_USERNAME \
--branch-pattern="^main$" \
--build-config=cloudbuild.yaml
Step 5: Grant Permissions
Cloud Build needs permission to deploy to Firebase:
# Get the Cloud Build service account
PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format='value(projectNumber)')
SERVICE_ACCOUNT="${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com"
# Grant Firebase Admin role
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT}" \
--role="roles/firebase.admin"
Step 6: Test Your Pipeline
Now push a commit to your main branch:
git add .
git commit -m "Set up CI/CD pipeline"
git push origin main
Watch the build progress in the Cloud Build console:
gcloud builds list --limit=5
Monitoring and Optimization
Build Time Optimization
You can speed up builds by caching dependencies:
steps:
# Cache node_modules
- name: 'node:18'
entrypoint: 'bash'
args:
- '-c'
- |
npm ci --cache .npm --prefer-offline
options:
machineType: 'E2_HIGHCPU_8' # Use faster machines
Cost Optimization
Cloud Build offers 120 free build-minutes per day. For a personal blog with occasional updates, you'll likely stay within the free tier!
Monitor your usage:
gcloud builds list --format="table(
id,
createTime.date('%Y-%m-%d'),
status,
timing.keys()
)"
Bonus: Preview Deployments
Create preview deployments for pull requests:
# cloudbuild-pr.yaml
steps:
- name: 'node:18'
entrypoint: npm
args: ['install']
- name: 'node:18'
entrypoint: npm
args: ['run', 'build']
- name: 'gcr.io/PROJECT_ID/firebase'
args: [
'hosting:channel:deploy',
'pr-$SHORT_SHA',
'--expires',
'7d',
'--project',
'PROJECT_ID'
]
Conclusion
You now have a fully automated CI/CD pipeline! Every push to your main branch will:
- ✅ Install dependencies
- ✅ Build your Next.js app
- ✅ Deploy to Firebase Hosting
- ✅ Invalidate CDN cache
- ✅ Be live in ~2-3 minutes
The best part? It's virtually free for personal projects and scales effortlessly as your traffic grows.
Next Steps:
- Add automated testing to your pipeline
- Set up custom domains
- Configure Cloud CDN for even better performance
Questions? Drop them in the comments or reach out on GitHub!