Deploy to Google Cloud Platform
Deploy your Bunty application to Google Cloud Platform (GCP) using services like Cloud Run, App Engine, Compute Engine, or GKE.
Prerequisites
- GCP account
gcloudCLI installed- Docker installed
Setup gcloud CLI
# Install gcloud CLI
# Download from: https://cloud.google.com/sdk/docs/install
# Initialize
gcloud init
# Set project
gcloud config set project YOUR_PROJECT_ID
# Authenticate
gcloud auth login
Option 1: Cloud Run (Recommended)
Cloud Run is the easiest way to deploy containerized applications with automatic scaling.
Create Dockerfile
FROM oven/bun:1-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .
EXPOSE 8080
CMD ["bun", "run", "src/main.ts"]
Deploy with One Command
# Deploy directly from source
gcloud run deploy bunty-app \
--source . \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--set-env-vars NODE_ENV=production,PORT=8080
Deploy from Container Registry
# Build and push to Artifact Registry
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/bunty-app
# Deploy
gcloud run deploy bunty-app \
--image gcr.io/YOUR_PROJECT_ID/bunty-app \
--platform managed \
--region us-central1 \
--allow-unauthenticated \
--port 8080 \
--cpu 1 \
--memory 512Mi \
--min-instances 0 \
--max-instances 10 \
--set-env-vars NODE_ENV=production
With Cloud SQL
# Create Cloud SQL instance
gcloud sql instances create bunty-db \
--database-version=POSTGRES_15 \
--tier=db-f1-micro \
--region=us-central1
# Create database
gcloud sql databases create bunty --instance=bunty-db
# Deploy with Cloud SQL connection
gcloud run deploy bunty-app \
--image gcr.io/YOUR_PROJECT_ID/bunty-app \
--add-cloudsql-instances YOUR_PROJECT_ID:us-central1:bunty-db \
--set-env-vars DATABASE_URL="postgresql://user:pass@/bunty?host=/cloudsql/YOUR_PROJECT_ID:us-central1:bunty-db"
Use Secrets
# Create secret
echo -n "your-secret-value" | gcloud secrets create jwt-secret --data-file=-
# Deploy with secrets
gcloud run deploy bunty-app \
--image gcr.io/YOUR_PROJECT_ID/bunty-app \
--set-secrets JWT_SECRET=jwt-secret:latest,DATABASE_URL=database-url:latest
Custom Domain
# Map custom domain
gcloud run services update bunty-app --platform managed --region us-central1
gcloud beta run domain-mappings create --service bunty-app --domain api.example.com
Option 2: App Engine
Create app.yaml
runtime: custom
env: flex
automatic_scaling:
min_num_instances: 1
max_num_instances: 10
cool_down_period_sec: 180
cpu_utilization:
target_utilization: 0.7
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
network:
forwarded_ports:
- 8080
env_variables:
NODE_ENV: 'production'
PORT: '8080'
Deploy
# Deploy to App Engine
gcloud app deploy
# View app
gcloud app browse
# View logs
gcloud app logs tail -s default
With Datastore
import { Datastore } from '@google-cloud/datastore';
const datastore = new Datastore();
async function saveUser(user: any) {
const key = datastore.key(['User', user.id]);
await datastore.save({
key,
data: user,
});
}
Option 3: Compute Engine (VM)
Create VM Instance
# Create instance
gcloud compute instances create bunty-vm \
--image-family=ubuntu-2204-lts \
--image-project=ubuntu-os-cloud \
--machine-type=e2-medium \
--zone=us-central1-a \
--tags=http-server,https-server
# Allow HTTP/HTTPS
gcloud compute firewall-rules create allow-http \
--allow tcp:80,tcp:443 \
--target-tags http-server,https-server
SSH and Setup
# SSH into instance
gcloud compute ssh bunty-vm --zone=us-central1-a
# Install Bun
curl -fsSL https://bun.sh/install | bash
source ~/.bashrc
# Clone and setup app
git clone https://github.com/yourusername/bunty-app.git
cd bunty-app
bun install --production
# Install PM2
npm install -g pm2
# Start app
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup
# Setup Nginx (same as AWS EC2 guide)
Create Instance from Image
# Create custom image
gcloud compute images create bunty-image \
--source-disk bunty-vm \
--source-disk-zone us-central1-a
# Create instance from image
gcloud compute instances create bunty-instance \
--image bunty-image \
--machine-type e2-medium \
--zone us-central1-a
Option 4: Google Kubernetes Engine (GKE)
Create GKE Cluster
# Create cluster
gcloud container clusters create bunty-cluster \
--num-nodes=3 \
--machine-type=e2-medium \
--region=us-central1 \
--enable-autoscaling \
--min-nodes=1 \
--max-nodes=5
# Get credentials
gcloud container clusters get-credentials bunty-cluster --region=us-central1
Deploy to GKE
# Build and push image
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/bunty-app
# Apply Kubernetes manifests
kubectl apply -f k8s/
# Or use this quick deployment:
kubectl create deployment bunty-app --image=gcr.io/YOUR_PROJECT_ID/bunty-app
kubectl expose deployment bunty-app --type=LoadBalancer --port=80 --target-port=3000
Full Kubernetes Setup
See Kubernetes deployment guide for complete configuration.
Cloud Build (CI/CD)
cloudbuild.yaml
steps:
# Run tests
- name: 'oven/bun:1'
entrypoint: bun
args: ['test']
# Build Docker image
- name: 'gcr.io/cloud-builders/docker'
args:
- 'build'
- '-t'
- 'gcr.io/$PROJECT_ID/bunty-app:$SHORT_SHA'
- '-t'
- 'gcr.io/$PROJECT_ID/bunty-app:latest'
- '.'
# Push to Container Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/bunty-app:$SHORT_SHA']
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECT_ID/bunty-app:latest']
# Deploy to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- 'run'
- 'deploy'
- 'bunty-app'
- '--image'
- 'gcr.io/$PROJECT_ID/bunty-app:$SHORT_SHA'
- '--region'
- 'us-central1'
- '--platform'
- 'managed'
- '--allow-unauthenticated'
images:
- 'gcr.io/$PROJECT_ID/bunty-app:$SHORT_SHA'
- 'gcr.io/$PROJECT_ID/bunty-app:latest'
options:
machineType: 'N1_HIGHCPU_8'
Create Trigger
# Connect repository
gcloud builds triggers create github \
--name=bunty-deploy \
--repo-name=bunty-app \
--repo-owner=yourusername \
--branch-pattern=^main$ \
--build-config=cloudbuild.yaml
Cloud Storage
Create Bucket
# Create bucket
gsutil mb gs://bunty-uploads
# Make public (if needed)
gsutil iam ch allUsers:objectViewer gs://bunty-uploads
Use in Application
import { Storage } from '@google-cloud/storage';
const storage = new Storage();
const bucket = storage.bucket('bunty-uploads');
async function upload(filename: string, buffer: Buffer) {
const file = bucket.file(filename);
await file.save(buffer, {
metadata: {
contentType: 'image/jpeg',
},
});
// Get public URL
const publicUrl = `https://storage.googleapis.com/bunty-uploads/${filename}`;
return publicUrl;
}
async function download(filename: string) {
const file = bucket.file(filename);
const [contents] = await file.download();
return contents;
}
Cloud SQL
Create PostgreSQL Instance
# Create instance
gcloud sql instances create bunty-db \
--database-version=POSTGRES_15 \
--tier=db-g1-small \
--region=us-central1 \
--root-password=your-password
# Create database
gcloud sql databases create bunty --instance=bunty-db
# Create user
gcloud sql users create bunty \
--instance=bunty-db \
--password=bunty-password
Connect from Application
import { DatabaseModule } from '@bunty/orm';
@Module({
imports: [
DatabaseModule.forRoot({
host: '/cloudsql/PROJECT_ID:us-central1:bunty-db',
database: 'bunty',
user: 'bunty',
password: process.env.DB_PASSWORD,
}),
],
})
export class AppModule {}
Memorystore (Redis)
Create Redis Instance
gcloud redis instances create bunty-cache \
--size=1 \
--region=us-central1 \
--redis-version=redis_7_0
Use in Application
import { Redis } from 'ioredis';
const redis = new Redis({
host: process.env.REDIS_HOST,
port: 6379,
});
await redis.set('key', 'value');
const value = await redis.get('key');
Secret Manager
Create Secrets
# Create secret
echo -n "my-secret-value" | gcloud secrets create my-secret --data-file=-
# Grant access
gcloud secrets add-iam-policy-binding my-secret \
--member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
Access in Application
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
const client = new SecretManagerServiceClient();
async function getSecret(name: string) {
const [version] = await client.accessSecretVersion({
name: `projects/PROJECT_ID/secrets/${name}/versions/latest`,
});
return version.payload.data.toString();
}
Monitoring
Cloud Logging
import { Logging } from '@google-cloud/logging';
const logging = new Logging();
const log = logging.log('bunty-app');
async function logInfo(message: string) {
const entry = log.entry({
severity: 'INFO',
resource: { type: 'global' },
}, message);
await log.write(entry);
}
Cloud Monitoring
# View metrics
gcloud monitoring time-series list --filter='metric.type="run.googleapis.com/request_count"'
# Create alert
gcloud alpha monitoring policies create \
--notification-channels=CHANNEL_ID \
--display-name="High CPU" \
--condition-threshold-value=0.8 \
--condition-display-name="CPU > 80%"
Load Balancing
Create Load Balancer
# Create backend service
gcloud compute backend-services create bunty-backend \
--global \
--health-checks bunty-health \
--protocol HTTP
# Create URL map
gcloud compute url-maps create bunty-lb \
--default-service bunty-backend
# Create target proxy
gcloud compute target-http-proxies create bunty-proxy \
--url-map bunty-lb
# Create forwarding rule
gcloud compute forwarding-rules create bunty-rule \
--global \
--target-http-proxy bunty-proxy \
--ports 80
Cost Optimization
- Use Cloud Run for variable workloads (pay per use)
- Enable auto-scaling
- Use Preemptible VMs for non-critical workloads
- Set up budget alerts
- Use Cloud CDN for static content
- Choose appropriate machine types
Best Practices
- Use Cloud Run for most workloads (easiest, auto-scaling)
- Enable Cloud Build for automated deployments
- Use Secret Manager for sensitive data
- Set up Cloud Monitoring for observability
- Use Cloud CDN for better performance
- Enable VPC for security
- Use Cloud Armor for DDoS protection
Next Steps
- Set up CI/CD with Cloud Build
- Configure monitoring
- Implement autoscaling
- Add CDN