Use Cases (Atualizado: 02/06/2026)

Deploy no GCP Cloud Run com Claude Code: guia prático

Publique uma API Node.js segura no Cloud Run com Docker, IAM, secrets, logs e rollback.

Deploy no GCP Cloud Run com Claude Code: guia prático

Cloud Run é uma boa escolha quando você quer publicar um serviço HTTP em contêiner sem operar Kubernetes, ECS ou uma frota de VMs. Diferente de Cloud Functions ou Lambda, você não precisa transformar tudo em pequenas funções. Uma API Express comum pode virar uma imagem Docker, e o Google Cloud cuida de HTTPS, revisões, escala e logs.

Este guia mostra como usar Claude Code para levar uma API TypeScript/Express do ambiente local até o Cloud Run. Ele inclui código executável, Dockerfile, teste local, Artifact Registry, gcloud run deploy, service account, IAM, Secret Manager, concorrência, instâncias mínimas, Cloud Logging, rollback de revisão, armadilhas de custo e uma prompt de revisão de deploy.

Em linguagem simples: Cloud Run é uma plataforma serverless para executar contêineres que respondem a HTTP. Artifact Registry é o repositório de imagens Docker. Secret Manager é o cofre de senhas e chaves de API. IAM é o sistema de permissões que define qual identidade acessa qual recurso.

Quando Cloud Run vence Functions ou Lambda

Cloud Run nem sempre é melhor que Cloud Functions ou Lambda. Para um handler de evento minúsculo, uma função pode ser mais simples. Cloud Run ganha quando o serviço já é uma aplicação HTTP ou quando você precisa de mais controle sobre runtime e dependências.

Caso de usoPor que Cloud Run encaixa
Receptor de webhooksStripe, GitHub e LINE viram rotas Express naturalmente
BFF ou API pequenaAuth, middleware, rotas e validação ficam em uma app Node.js normal
Endpoint HTTP para batch agendadoCloud Scheduler pode chamar via HTTP sem outro framework de jobs
API leve de IA ou dadosDependências nativas e binários customizados ficam no contêiner

Para workers longos, revise CPU e custo antes. Cloud Run é forte em serviços orientados a requisições, mas loops em segundo plano exigem mais cuidado.

Serviço Express executável

Cloud Run informa a porta pela variável PORT. O serviço deve ler esse valor, expor /health e encerrar corretamente ao receber 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();
});

Teste primeiro localmente:

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 e revisão com Claude Code

Peça ao Claude Code uma revisão de produção, não apenas geração. Os pontos críticos são imagem pequena, dependências de produção, usuário não root, .dockerignore, suporte a PORT e riscos de segurança/custo.

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 e primeiro deploy

Artifact Registry armazena a imagem Docker. Configure a autenticação do host regional, crie o repositório e envie a imagem.

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"

Crie uma service account de runtime antes do 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

Para API interna, remova --allow-unauthenticated e conceda Cloud Run Invoker apenas aos chamadores necessários.

Secret Manager, IAM e segurança

Não grave secrets em --set-env-vars. Guarde no Secret Manager e injete no 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"

Prefira IAM por secret em vez de papéis amplos no projeto. Isso reduz o impacto de erro de configuração.

Concorrência, instâncias mínimas e custo

Concorrência é o número máximo de requisições simultâneas por instância. Valores altos reduzem instâncias, mas podem saturar o banco ou APIs externas.

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

Use min-instances 0 em desenvolvimento e serviços de baixo tráfego. Use 1 ou mais se um webhook ou API de produção não tolera cold start. Comece webhooks em 20-40, BFF/API em 40-80, e ajuste com latência p95, conexões de banco e erros.

Logs e rollback

Cloud Run envia logs de requisição, contêiner e sistema para Cloud Logging. Em Node.js, stdout/stderr costuma ser suficiente.

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

Cada deploy ou mudança cria uma revision imutável. Para voltar, mova o tráfego para uma revision estável.

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 revisão antes de produção:

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.
"

Armadilhas comuns

Imagens grandes atrasam build, push e cold start. Secrets em variáveis comuns podem aparecer no histórico ou no CI. min-instances 1 reduz latência, mas cobra mesmo sem tráfego. Concorrência alta pode derrubar banco e SaaS externos. Rollback deve ser ensaiado antes de um incidente.

Referências e próximo passo

Cloud Run é um meio-termo prático: mais flexível que funções puras e mais leve que ECS ou Kubernetes. Para transformar prompts, revisões e guardrails de deploy em processo de equipe, veja treinamento e consultoria Claude Code.

Nota de verificação prática

O exemplo foi verificado com npm run dev, acesso Docker a /health, suporte a PORT e validação de variáveis obrigatórias. Antes de produção, confira permissões reais do Artifact Registry, IAM do Secret Manager, consultas no Cloud Logging e um ensaio de rollback com update-traffic.

#claude-code #gcp #cloud-run #docker #typescript #serverless
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.