Use Cases (Diperbarui: 2/6/2026)

Deploy ke GCP Cloud Run dengan Claude Code: panduan praktis

Deploy API Node.js yang aman di Cloud Run dengan Docker, IAM, secrets, logs, dan rollback.

Deploy ke GCP Cloud Run dengan Claude Code: panduan praktis

Cloud Run cocok ketika Anda ingin memublikasikan layanan HTTP berbasis kontainer tanpa mengoperasikan Kubernetes, ECS, atau banyak VM. Dibanding Cloud Functions atau Lambda, Anda tidak perlu memecah seluruh aplikasi menjadi fungsi kecil. API Express biasa bisa dikemas sebagai image Docker, lalu Google Cloud menangani HTTPS, revision, scaling, dan logs.

Panduan ini menunjukkan cara memakai Claude Code untuk membawa API TypeScript/Express dari lokal ke Cloud Run. Isinya mencakup kode yang bisa dijalankan, Dockerfile, tes lokal, Artifact Registry, gcloud run deploy, service account, IAM, Secret Manager, concurrency, min instances, Cloud Logging, rollback revision, jebakan biaya, dan prompt review deployment.

Secara sederhana: Cloud Run adalah platform serverless untuk menjalankan kontainer yang merespons HTTP. Artifact Registry adalah tempat menyimpan image Docker. Secret Manager adalah brankas untuk password dan API key. IAM adalah sistem permission yang menentukan identity mana boleh mengakses resource apa.

Kapan Cloud Run lebih cocok dari Functions atau Lambda

Cloud Run tidak selalu lebih baik dari Cloud Functions atau Lambda. Untuk event handler yang sangat kecil, function bisa lebih sederhana. Cloud Run unggul ketika layanan sudah berupa aplikasi HTTP atau ketika runtime dan dependency perlu lebih banyak kontrol.

Use caseMengapa Cloud Run cocok
Penerima webhookStripe, GitHub, dan LINE bisa dipetakan alami ke route Express
BFF atau API kecilAuth, middleware, routing, dan validasi tetap berada di satu app Node.js
Endpoint HTTP untuk batch terjadwalCloud Scheduler bisa memanggil via HTTP tanpa framework job terpisah
API AI/data ringanDependency native dan binary custom bisa dimasukkan ke kontainer

Untuk worker yang berjalan lama, review CPU allocation dan biaya terlebih dahulu. Cloud Run kuat untuk layanan berbasis request, tetapi bukan jawaban default untuk background loop.

Service Express yang bisa dijalankan

Cloud Run memberikan port melalui environment variable PORT. Service harus membaca nilai ini, menyediakan /health, dan shutdown dengan rapi saat menerima SIGTERM.

{
  "name": "cloud-run-claude-code-api",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "tsx src/index.ts",
    "build": "tsc",
    "start": "node dist/index.js",
    "test": "node --test"
  },
  "dependencies": {
    "express": "^4.19.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.21",
    "@types/node": "^22.10.0",
    "tsx": "^4.19.2",
    "typescript": "^5.7.2"
  }
}
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*.ts"]
}
import express from "express";

const app = express();
app.use(express.json());

const requiredEnv = ["DATABASE_URL", "JWT_SECRET"];
for (const key of requiredEnv) {
  if (!process.env[key]) {
    console.error(`Missing required environment variable: ${key}`);
    process.exit(1);
  }
}

app.get("/health", (_req, res) => {
  res.status(200).json({ ok: true, service: "myapp-api" });
});

app.post("/webhooks/example", (req, res) => {
  console.log("webhook_received", {
    eventType: req.body?.type ?? "unknown",
    receivedAt: new Date().toISOString()
  });
  res.status(202).json({ accepted: true });
});

app.get("/config-check", (_req, res) => {
  res.json({
    nodeEnv: process.env.NODE_ENV ?? "development",
    hasDatabaseUrl: Boolean(process.env.DATABASE_URL),
    hasJwtSecret: Boolean(process.env.JWT_SECRET)
  });
});

const port = Number(process.env.PORT ?? 8080);
const server = app.listen(port, () => {
  console.log(`listening on ${port}`);
});

process.on("SIGTERM", () => {
  console.log("SIGTERM received, closing HTTP server");
  server.close(() => process.exit(0));
  setTimeout(() => process.exit(1), 30000).unref();
});

Tes lokal dulu:

npm install
DATABASE_URL="postgresql://local" JWT_SECRET="local-secret" npm run dev
curl http://localhost:8080/health
curl -X POST http://localhost:8080/webhooks/example \
  -H "Content-Type: application/json" \
  -d '{"type":"demo.created"}'

Dockerfile dan review Claude Code

Minta Claude Code melakukan review produksi, bukan hanya membuat file. Periksa image runtime kecil, dependency production saja, user non-root, .dockerignore, dukungan PORT, serta risiko keamanan dan biaya.

claude -p "
Review and improve this Cloud Run Docker setup.
Requirements:
- Node.js 22 LTS, TypeScript, Express
- production dependencies only in runtime image
- run as a non-root user
- listen on the PORT environment variable
- include .dockerignore
- explain any Cloud Run security or cost risks
Return the final Dockerfile and a short review checklist.
"
FROM node:22-alpine AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY tsconfig.json ./
COPY src ./src
RUN npm run build

FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=8080

RUN addgroup -S appgroup && adduser -S appuser -G appgroup

COPY package*.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --from=builder /app/dist ./dist

USER appuser
EXPOSE 8080
CMD ["node", "--max-old-space-size=384", "dist/index.js"]
node_modules
dist
.env
.env.*
*.log
.git
.gitignore
Dockerfile
README.md
docker build -t myapp-api:local .
docker run --rm -p 8080:8080 \
  -e PORT=8080 \
  -e DATABASE_URL="postgresql://local" \
  -e JWT_SECRET="local-secret" \
  myapp-api:local
curl http://localhost:8080/health

Artifact Registry dan deploy pertama

Artifact Registry menyimpan image Docker. Konfigurasikan autentikasi Docker untuk host regional, buat repository, lalu push image.

PROJECT_ID="my-project-123"
REGION="asia-northeast1"
REPOSITORY="myapp"
SERVICE="myapp-api"
IMAGE="$REGION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/api:v1.0.0"

gcloud config set project "$PROJECT_ID"
gcloud services enable run.googleapis.com artifactregistry.googleapis.com secretmanager.googleapis.com logging.googleapis.com

gcloud artifacts repositories create "$REPOSITORY" \
  --repository-format=docker \
  --location="$REGION" \
  --description="Docker images for myapp"

gcloud auth configure-docker "$REGION-docker.pkg.dev"
docker build -t "$IMAGE" .
docker push "$IMAGE"

Buat service account runtime khusus sebelum deploy.

gcloud iam service-accounts create myapp-run \
  --display-name="Cloud Run runtime for myapp"

SERVICE_ACCOUNT="myapp-run@$PROJECT_ID.iam.gserviceaccount.com"

gcloud run deploy "$SERVICE" \
  --image "$IMAGE" \
  --region "$REGION" \
  --platform managed \
  --service-account "$SERVICE_ACCOUNT" \
  --memory 512Mi \
  --cpu 1 \
  --concurrency 80 \
  --min-instances 0 \
  --max-instances 20 \
  --allow-unauthenticated \
  --set-env-vars NODE_ENV=production \
  --port 8080

Untuk API internal, hapus --allow-unauthenticated dan berikan Cloud Run Invoker hanya kepada caller yang perlu.

Secret Manager, IAM, dan keamanan

Jangan menulis secret di --set-env-vars. Simpan di Secret Manager dan inject ke Cloud Run.

echo -n "postgresql://user:password@host:5432/app" | \
  gcloud secrets create DATABASE_URL --data-file=-

echo -n "replace-with-long-random-value" | \
  gcloud secrets create JWT_SECRET --data-file=-

gcloud secrets add-iam-policy-binding DATABASE_URL \
  --member="serviceAccount:$SERVICE_ACCOUNT" \
  --role="roles/secretmanager.secretAccessor"

gcloud secrets add-iam-policy-binding JWT_SECRET \
  --member="serviceAccount:$SERVICE_ACCOUNT" \
  --role="roles/secretmanager.secretAccessor"

gcloud run services update "$SERVICE" \
  --region "$REGION" \
  --set-secrets "DATABASE_URL=DATABASE_URL:latest,JWT_SECRET=JWT_SECRET:latest"

IAM per secret lebih aman daripada role project yang terlalu luas. Dampak kesalahan konfigurasi menjadi lebih kecil.

Concurrency, min instances, dan biaya

Concurrency adalah jumlah request simultan maksimum yang diproses satu instance. Nilai tinggi bisa mengurangi instance, tetapi database pool atau API eksternal bisa lebih dulu penuh.

gcloud run services update "$SERVICE" \
  --region "$REGION" \
  --concurrency 40 \
  --min-instances 1 \
  --max-instances 20 \
  --cpu-throttling

Gunakan min-instances 0 untuk development dan traffic rendah. Gunakan 1 atau lebih jika webhook atau API production tidak boleh terkena cold start. Mulai webhook di 20-40, BFF/API di 40-80, lalu sesuaikan dengan p95 latency, koneksi database, dan error rate.

Cloud Logging dan rollback

Cloud Run mengirim request logs, container logs, dan system logs ke Cloud Logging. Untuk Node.js, stdout/stderr biasanya cukup.

gcloud run services logs read "$SERVICE" \
  --region "$REGION" \
  --limit 20

gcloud logging read \
  "resource.type=cloud_run_revision AND resource.labels.service_name=$SERVICE" \
  --limit 20 \
  --format=json

Setiap deploy atau perubahan konfigurasi membuat revision immutable. Jika bermasalah, pindahkan traffic ke revision yang stabil.

gcloud run revisions list \
  --service "$SERVICE" \
  --region "$REGION"

gcloud run services update-traffic "$SERVICE" \
  --region "$REGION" \
  --to-revisions myapp-api-00012-abc=100

Prompt review sebelum production:

claude -p "
Act as a Cloud Run deployment reviewer.
Review package.json, Dockerfile, src/index.ts, and the gcloud commands below.
Find blockers before production:
- Cloud Run PORT handling
- SIGTERM graceful shutdown
- non-root container
- Secret Manager usage
- service account and IAM least privilege
- concurrency, min instances, max instances, and cost risks
- Cloud Logging observability
- rollback command for the previous revision
Return: critical issues, recommended fixes, and commands to verify after deploy.
"

Jebakan umum

Image besar memperlambat build, push, dan cold start. Secret di environment variable biasa bisa bocor ke history atau log CI. min-instances 1 menurunkan latency, tetapi tetap menambah biaya saat idle. Concurrency terlalu tinggi bisa menekan database dan SaaS eksternal. Perintah rollback sebaiknya dilatih sebelum insiden terjadi.

Referensi dan langkah berikutnya

Cloud Run adalah jalan tengah yang praktis: lebih fleksibel dari platform function-only dan lebih ringan daripada ECS atau Kubernetes. Untuk menerapkan prompt, checklist review, dan guardrail deployment di tim, lihat training dan konsultasi Claude Code.

Catatan verifikasi langsung

Contoh ini dicek dengan npm run dev, akses Docker ke /health, handling PORT, dan validasi environment wajib. Sebelum production, cek permission Artifact Registry nyata, IAM Secret Manager, query Cloud Logging, dan latihan rollback dengan update-traffic.

#claude-code #gcp #cloud-run #docker #typescript #serverless
Gratis

PDF gratis: cheatsheet Claude Code

Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.

Kami menjaga datamu dan tidak mengirim spam.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.