Use Cases (Aktualisiert: 2.6.2026)

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.

Mit Claude Code zu GCP Cloud Run deployen: Praxisleitfaden

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.

AnwendungsfallWarum Cloud Run passt
Webhook-EmpfängerStripe-, GitHub- oder LINE-POSTs lassen sich natürlich als Express-Routen abbilden
Kleiner BFF/API-ServerAuthentifizierung, Middleware, Routing und Validierung bleiben in einer Node.js-App
Geplanter HTTP-Batch-EndpunktCloud Scheduler kann per HTTP aufrufen, ohne ein separates Job-System
Leichte KI- oder Daten-APINative 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 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.

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

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.

Masa

Über den Autor

Masa

Engineer für praktische Claude-Code-Workflows und Team-Einführung.