Use Cases (Mis à jour: 02/06/2026)

Déployer sur GCP Cloud Run avec Claude Code : guide pratique

Déployez une API Node.js sécurisée sur Cloud Run avec Docker, IAM, secrets, logs et rollback.

Déployer sur GCP Cloud Run avec Claude Code : guide pratique

Cloud Run est un bon choix quand vous voulez publier un service HTTP conteneurisé sans exploiter Kubernetes, ECS ou une flotte de VM. Contrairement à Cloud Functions ou Lambda, vous n’avez pas besoin de découper toute l’application en petites fonctions. Vous pouvez prendre une API Express classique, l’empaqueter en image Docker et laisser Google Cloud gérer HTTPS, révisions, scaling et logs.

Ce guide montre comment utiliser Claude Code pour amener une API TypeScript/Express de votre poste local à Cloud Run. Il couvre le code exécutable, le Dockerfile, le test local, Artifact Registry, gcloud run deploy, le compte de service, IAM, Secret Manager, la concurrence, les instances minimales, Cloud Logging, le rollback de révision, les pièges de coût et une prompt de revue avant déploiement.

En clair : Cloud Run est une plateforme serverless pour exécuter des conteneurs qui répondent à des requêtes HTTP. Artifact Registry est le dépôt d’images Docker. Secret Manager est le coffre pour mots de passe et clés API. IAM est le système de permissions qui détermine quelle identité peut accéder à quelle ressource.

Quand Cloud Run bat Functions ou Lambda

Cloud Run n’est pas toujours supérieur à Cloud Functions ou Lambda. Pour un minuscule handler d’événement, une fonction peut être plus simple. Cloud Run devient plus intéressant quand le service est déjà une application HTTP ou quand le runtime doit être plus contrôlé.

Cas d’usagePourquoi Cloud Run convient
Récepteur de webhooksStripe, GitHub ou LINE se modélisent naturellement en routes Express
Petit BFF ou serveur APIAuth, middleware, routage et validation restent dans une application Node.js normale
Endpoint HTTP de traitement planifiéCloud Scheduler peut l’appeler sans créer un autre framework de jobs
API légère IA ou donnéesDépendances natives et binaires personnalisés restent dans le conteneur

Pour un worker longuement actif, vérifiez CPU et coût. Cloud Run est excellent pour les services déclenchés par requêtes, moins évident pour des boucles de fond permanentes.

Service Express exécutable

Cloud Run fournit le port via la variable PORT. Le service doit la lire, exposer /health et s’arrêter proprement quand Cloud Run envoie 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();
});

Testez d’abord en local :

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 et revue Claude Code

Demandez à Claude Code une revue de production, pas seulement une génération de fichier. Les points clés sont : image runtime compacte, dépendances de production uniquement, utilisateur non root, .dockerignore, prise en charge de PORT, risques sécurité et coût.

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 et premier déploiement

Artifact Registry stocke l’image Docker. Configurez l’authentification Docker du host régional, créez le dépôt, puis poussez l’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"

Créez un compte de service runtime dédié avant le déploiement.

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

Pour une API interne, retirez --allow-unauthenticated et donnez Cloud Run Invoker uniquement aux appelants autorisés.

Secret Manager, IAM et sécurité

N’écrivez pas les secrets dans --set-env-vars. Stockez-les dans Secret Manager et injectez-les dans 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"

Préférez des permissions au niveau du secret plutôt qu’un rôle large sur le projet.

Concurrence, instances minimales et coût

La concurrence est le nombre maximum de requêtes simultanées traitées par une instance. Une valeur élevée réduit les instances, mais peut saturer la base ou une API externe.

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

Gardez min-instances 0 en développement ou pour un service très peu utilisé. Passez à 1 ou plus si une API ou un webhook de production ne tolère pas le cold start. Démarrez les webhooks vers 20-40, les BFF/API vers 40-80, puis ajustez avec la latence p95, les connexions DB et le taux d’erreur.

Logs et rollback

Cloud Run envoie les logs de requête, conteneur et système à Cloud Logging. Pour Node.js, stdout/stderr suffit souvent.

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

Chaque déploiement ou changement de configuration crée une révision immuable. Pour revenir en arrière, déplacez le trafic vers une révision stable.

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

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

Prompt de revue avant 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.
"

Pièges courants

Les grosses images ralentissent build, push et cold start. Les secrets en variables ordinaires peuvent finir dans l’historique ou les logs CI. min-instances 1 réduit la latence, mais facture même sans trafic. Une concurrence trop haute peut épuiser la base ou les APIs tierces. Le rollback doit être testé avant l’incident.

Références et suite

Cloud Run offre un compromis pratique : plus flexible qu’une plateforme de fonctions, plus léger qu’ECS ou Kubernetes. Pour mettre en place des prompts, revues et garde-fous de déploiement en équipe, consultez la formation et le conseil Claude Code.

Note de vérification terrain

L’exemple a été vérifié avec npm run dev, l’accès Docker à /health, la gestion de PORT et la validation des variables obligatoires. Avant production, répétez avec les permissions Artifact Registry réelles, l’IAM Secret Manager, les requêtes Cloud Logging et un exercice de rollback via update-traffic.

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

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.