Mit Claude Code zu GCP Cloud Run deployen: Praxisleitfaden
Eine sichere Node.js-API mit Docker, IAM, Secrets, Logs und Rollback auf Cloud Run bereitstellen.
Cloud Run passt gut, wenn Sie einen containerisierten HTTP-Service veröffentlichen möchten, ohne Kubernetes, ECS oder eine VM-Flotte zu betreiben. Im Vergleich zu Cloud Functions oder Lambda müssen Sie die Anwendung nicht in viele kleine Funktionen zerlegen. Eine normale Express-API kann als Docker-Image gebaut werden, während Google Cloud HTTPS, Revisionen, Skalierung und Logs übernimmt.
Dieser Leitfaden zeigt, wie Claude Code beim Weg von einer TypeScript/Express-API zu Cloud Run hilft. Enthalten sind lauffähiger Code, Dockerfile, lokaler Test, Artifact Registry, gcloud run deploy, Service Account, IAM, Secret Manager, Concurrency, minimale Instanzen, Cloud Logging, Revision-Rollback, Kostenfallen und ein Prompt für die Deployment-Prüfung.
Einfach gesagt: Cloud Run führt Container serverlos aus, die HTTP-Anfragen beantworten. Artifact Registry ist der Speicher für Docker-Images. Secret Manager ist der Tresor für Passwörter und API-Schlüssel. IAM ist das Berechtigungssystem, das festlegt, welche Identität auf welche Ressource zugreifen darf.
Wann Cloud Run besser passt als Functions oder Lambda
Für sehr kleine Event-Handler können Cloud Functions oder Lambda einfacher sein. Cloud Run lohnt sich, wenn der Dienst bereits eine HTTP-Anwendung ist oder wenn Sie mehr Kontrolle über Runtime, Systempakete und Abhängigkeiten brauchen.
| Anwendungsfall | Warum Cloud Run passt |
|---|---|
| Webhook-Empfänger | Stripe-, GitHub- oder LINE-POSTs lassen sich natürlich als Express-Routen abbilden |
| Kleiner BFF/API-Server | Authentifizierung, Middleware, Routing und Validierung bleiben in einer Node.js-App |
| Geplanter HTTP-Batch-Endpunkt | Cloud Scheduler kann per HTTP aufrufen, ohne ein separates Job-System |
| Leichte KI- oder Daten-API | Native Abhängigkeiten und eigene Binärdateien bleiben im Container |
Für dauerhaft laufende Worker müssen CPU-Zuteilung und Kosten geprüft werden. Cloud Run ist stark bei request-getriebenen Diensten, aber nicht automatisch die beste Wahl für Endlosschleifen im Hintergrund.
Lauffähiger Express-Service
Cloud Run übergibt den Port über die Umgebungsvariable PORT. Der Dienst sollte diesen Wert lesen, /health anbieten und bei SIGTERM sauber schließen.
{
"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();
});
Lokal testen:
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 und Claude-Code-Review
Bitten Sie Claude Code nicht nur um Generierung, sondern um eine Produktionsprüfung: kleines Runtime-Image, nur Produktionsabhängigkeiten, Non-root-User, .dockerignore, PORT-Unterstützung sowie Sicherheits- und Kostenrisiken.
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 und erster Deploy
Artifact Registry speichert das Docker-Image. Richten Sie Docker-Authentifizierung für die Region ein, erstellen Sie das Repository und pushen Sie das 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"
Vor dem Deploy wird ein eigener Runtime-Service-Account angelegt.
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
Für interne APIs entfernen Sie --allow-unauthenticated und vergeben Cloud Run Invoker nur an berechtigte Aufrufer.
Secret Manager, IAM und Sicherheit
Schreiben Sie Secrets nicht in --set-env-vars. Speichern Sie sie in Secret Manager und injizieren Sie sie in 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"
Secret-spezifisches IAM ist besser als breite Projektrollen. Es begrenzt den Schaden bei Fehlkonfigurationen.
Concurrency, minimale Instanzen und Kosten
Concurrency ist die maximale Zahl gleichzeitiger Requests pro Instanz. Höhere Werte reduzieren Instanzen, können aber Datenbankpools oder externe APIs überlasten.
gcloud run services update "$SERVICE" \
--region "$REGION" \
--concurrency 40 \
--min-instances 1 \
--max-instances 20 \
--cpu-throttling
Für Entwicklung und wenig Traffic ist min-instances 0 meist richtig. Für produktive Webhooks oder APIs ohne Cold-Start-Toleranz prüfen Sie 1 oder mehr. Webhooks starten oft bei 20-40, BFF/API bei 40-80; danach entscheiden p95-Latenz, DB-Verbindungen und Fehlerrate.
Logs und Rollback
Cloud Run schreibt Request-, Container- und Systemlogs nach Cloud Logging. Für Node.js reicht stdout/stderr häufig aus.
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
Jeder Deploy und jede Konfigurationsänderung erzeugt eine unveränderliche Revision. Rollback bedeutet, Traffic auf eine bekannte gute Revision zu setzen.
gcloud run revisions list \
--service "$SERVICE" \
--region "$REGION"
gcloud run services update-traffic "$SERVICE" \
--region "$REGION" \
--to-revisions myapp-api-00012-abc=100
Prompt für die Prüfung vor Produktion:
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.
"
Häufige Fallen
Große Images verlangsamen Build, Push und Cold Start. Secrets in normalen Umgebungsvariablen landen leicht in Shell- oder CI-Logs. min-instances 1 senkt Latenz, kostet aber auch ohne Traffic. Zu hohe Concurrency kann Datenbanken und SaaS-APIs überfordern. Rollback-Befehle sollten vor einem Incident geübt werden.
Quellen und nächster Schritt
- Cloud Run Dokumentation
- Container-Images zu Cloud Run deployen
- Artifact Registry Docker-Authentifizierung
- Secrets für Cloud Run konfigurieren
- Cloud Run Logging
- Cloud Run Rollbacks und Traffic-Migration
- Claude Code Docker-Integration
- Claude Code AWS ECS/Fargate Guide
- Claude Code Sicherheitsbest Practices
Cloud Run ist ein pragmatischer Mittelweg: flexibler als reine Functions, leichter zu betreiben als ECS oder Kubernetes. Für Teamprozesse rund um Prompts, Reviews und Deployment-Leitplanken siehe Claude Code Training und Beratung.
Praktische Verifikationsnotiz
Das Beispiel wurde mit lokalem npm run dev, Docker-Zugriff auf /health, PORT-Handling und Pflichtvariablen geprüft. Vor Produktion sollten reale Artifact-Registry-Rechte, Secret-Manager-IAM, Cloud-Logging-Abfragen und ein Rollback-Test mit update-traffic folgen.
Kostenloses PDF: Claude-Code-Cheatsheet
E-Mail eintragen und eine Seite mit Befehlen, Review-Gewohnheiten und sicheren Workflows herunterladen.
Wir schützen Ihre Daten und senden keinen Spam.
Über den Autor
Masa
Engineer für praktische Claude-Code-Workflows und Team-Einführung.
Ähnliche Artikel
Claude Code Workflow von Obsidian zu CLAUDE.md
Obsidian-Arbeitsnotizen in CLAUDE.md-Betriebsnotizen verwandeln und Kontext nicht ständig neu erklären.
Claude Code Revenue CTA Routing: Artikel zu PDF, Gumroad und Beratung führen
Ein Claude-Code-Ablauf, der Leser nach Absicht zu Gratis-PDF, Gumroad oder Beratung führt.
Claude-Code-Team-Handoff-Regeln: Belege, Berechtigungen, Rollback und Umsatzpfade
Ein praktisches Claude-Code-Handoff für Review-Belege, Berechtigungen, Rollback, Gratis-PDF, Gumroad und Beratung.