Déployez vos containers Docker sur GCP Cloud Run : scaling automatique 0 vers N, gcloud CLI, Artifact Registry, IAM et CI/CD via Cloud Build.
Architecture Cloud Run et modèle d'exécution
Google Cloud Run est un service de calcul serverless qui exécute n'importe quel container Docker compatible Linux/amd64 (ou arm64). Contrairement à AWS Lambda qui impose des runtimes officiels, Cloud Run accepte un simple Dockerfile avec un binaire qui écoute sur le port $PORT (par défaut 8080). Cette flexibilité permet d'y déployer aussi bien une API Node.js, un service Go, une application PHP/Symfony, qu'un binaire Rust ultra-optimisé.
Le modèle d'exécution repose sur trois piliers : scale-to-zero (aucune instance ne tourne sans trafic), concurrence par instance (jusqu'à 1000 requêtes simultanées sur la même instance, contrairement à Lambda qui limite à 1) et facturation à la milliseconde CPU. Une instance reste chaude environ 15 minutes après la dernière requête pour absorber les pics suivants sans cold start.
Schéma logique
┌──────────────┐ HTTPS ┌────────────────────┐ pull ┌─────────────────────┐
│ Client web │ ─────────> │ Cloud Run (LB) │ <─────── │ Artifact Registry │
│ (browser) │ │ *.run.app │ │ europe-west1-docker│
└──────────────┘ └────────────────────┘ └─────────────────────┘
│
autoscaling │ min=0, max=100
▼
┌────────────────────┐
│ Instances Docker │ ─── Secret Manager (secrets)
│ (concurrency=80) │ ─── VPC Connector ─── Cloud SQL
└────────────────────┘
Cloud Run vs Lambda vs Fargate
| Critère | GCP Cloud Run | AWS Lambda | AWS Fargate |
|---|---|---|---|
| Format | Container Docker | Runtime géré ou container (10 Go max) | Container Docker |
| Scale-to-zero | Oui (par défaut) | Oui | Non (min 1 task) |
| Concurrence par instance | 1 à 1000 requêtes | 1 (1 instance = 1 requête) | Illimitée (selon process) |
| Timeout max requête | 60 minutes | 15 minutes | Illimité (long-running) |
| RAM max | 32 Go | 10 Go | 120 Go |
| Free tier mensuel | 2 M requêtes | 1 M requêtes | Aucun |
| Coût ~ /M requêtes CPU | ~ 0,40 $ | ~ 0,20 $ + GB-s | Forfait par task/h |
Setup gcloud CLI et Artifact Registry
La gcloud CLI est le couteau suisse pour piloter GCP. Avant tout déploiement, il faut l'installer, s'authentifier, créer un projet et activer les APIs nécessaires. Artifact Registry est le successeur officiel de Container Registry — c'est là que vivent les images Docker que Cloud Run vient tirer.
Installation et authentification
# Linux/macOS — installeur officiel
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
# Windows (PowerShell)
# Télécharger https://cloud.google.com/sdk/docs/install
# Vérification
gcloud --version
# Google Cloud SDK 478.0.0
# bq 2.1.4
# core 2024.05.10
# Authentification interactive (ouvre le navigateur)
gcloud auth login
# Authentification pour Docker pousser les images
gcloud auth configure-docker europe-west1-docker.pkg.dev
Créer le projet et activer les APIs
# Créer un nouveau projet GCP (l'ID doit être globalement unique)
export PROJECT_ID="afa-cloudrun-demo-$(date +%s)"
gcloud projects create "$PROJECT_ID" --name="AFA Cloud Run Demo"
# Définir comme projet actif
gcloud config set project "$PROJECT_ID"
# Lier un compte de facturation (obligatoire même pour le free tier)
gcloud billing projects link "$PROJECT_ID" \
--billing-account=0X0X0X-0X0X0X-0X0X0X
# Activer toutes les APIs nécessaires en une commande
gcloud services enable \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
secretmanager.googleapis.com \
sqladmin.googleapis.com \
vpcaccess.googleapis.com \
logging.googleapis.com \
monitoring.googleapis.com
Créer un repository Artifact Registry
# Repository Docker dans la région europe-west1 (Belgique)
gcloud artifacts repositories create afa-services \
--repository-format=docker \
--location=europe-west1 \
--description="Images Cloud Run AngularForAll"
# Lister les repositories
gcloud artifacts repositories list
# Format complet d'une image :
# europe-west1-docker.pkg.dev/PROJECT_ID/afa-services/IMAGE_NAME:TAG
europe-west1 (Belgique) ou europe-west9 (Paris) offrent les meilleurs résultats. Toujours co-localiser Artifact Registry, Cloud Run et Cloud SQL dans la même région pour éviter les frais de sortie réseau inter-régions.
Déployer un container Node.js Express
Construisons une API Node.js Express simple, conteneurisons-la avec un Dockerfile multi-stage optimisé, puis déployons-la sur Cloud Run en une commande. L'image finale passera de 1,1 Go (Node.js complet) à 180 Mo grâce à node:20-alpine et au multi-stage.
Code applicatif minimal
// server.js — API Express qui écoute sur $PORT (Cloud Run requirement)
const express = require('express');
const app = express();
// CRUCIAL : Cloud Run injecte la variable PORT (8080 par défaut)
const PORT = process.env.PORT || 8080;
app.get('/', (req, res) => {
res.json({
message: 'Hello from Cloud Run !',
revision: process.env.K_REVISION || 'local',
service: process.env.K_SERVICE || 'unknown'
});
});
app.get('/health', (req, res) => res.status(200).send('OK'));
app.listen(PORT, () => {
console.log(`API Cloud Run écoute sur le port ${PORT}`);
});
// package.json
{
"name": "afa-cloudrun-api",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.19.2"
}
}
Dockerfile multi-stage optimisé
# Dockerfile — multi-stage pour minimiser la taille finale
# ----- Stage 1 : build & installation des dépendances de prod -----
FROM node:20-alpine AS builder
WORKDIR /app
# Copier d'abord package.json pour profiter du cache Docker
COPY package*.json ./
RUN npm ci --only=production --no-audit --no-fund
# Copier le reste du code source
COPY . .
# ----- Stage 2 : runtime minimal (180 Mo) -----
FROM node:20-alpine AS runtime
WORKDIR /app
# Utilisateur non-root (sécurité)
RUN addgroup -S nodejs && adduser -S nodeapp -G nodejs
USER nodeapp
# Copier uniquement le strict nécessaire depuis le builder
COPY --from=builder --chown=nodeapp:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodeapp:nodejs /app/server.js ./
COPY --from=builder --chown=nodeapp:nodejs /app/package.json ./
# Cloud Run injecte $PORT — exposer 8080 par défaut
EXPOSE 8080
ENV NODE_ENV=production
CMD ["node", "server.js"]
.dockerignore pour accélérer le build
# .dockerignore — exclut les fichiers inutiles du contexte de build
node_modules
npm-debug.log
.git
.gitignore
.env
.env.local
README.md
*.md
.vscode
.idea
coverage
test
__tests__
*.test.js
Déploiement en une commande avec --source
# Cloud Build construit l'image automatiquement à partir du source
# (pas besoin de Docker installé localement)
gcloud run deploy afa-api \
--source . \
--region europe-west1 \
--platform managed \
--allow-unauthenticated \
--memory 512Mi \
--cpu 1 \
--min-instances 0 \
--max-instances 10 \
--concurrency 80 \
--timeout 60s \
--port 8080
# Output attendu :
# Service [afa-api] revision [afa-api-00001-abc] has been deployed
# Service URL: https://afa-api-xxxxxxxxxx-ew.a.run.app
Build manuel + push (alternative)
# Build local avec Docker (utile pour tester avant déploiement)
docker build -t afa-api:1.0.0 .
# Tag pour Artifact Registry
docker tag afa-api:1.0.0 \
europe-west1-docker.pkg.dev/$PROJECT_ID/afa-services/afa-api:1.0.0
# Push vers Artifact Registry
docker push \
europe-west1-docker.pkg.dev/$PROJECT_ID/afa-services/afa-api:1.0.0
# Déployer cette image précise sur Cloud Run
gcloud run deploy afa-api \
--image europe-west1-docker.pkg.dev/$PROJECT_ID/afa-services/afa-api:1.0.0 \
--region europe-west1 \
--allow-unauthenticated
Paramètres d'autoscaling fins
# Maximiser le throughput d'une instance (concurrency élevée)
gcloud run services update afa-api \
--region europe-west1 \
--concurrency 250 \
--cpu 2 \
--memory 1Gi
# Toujours garder 1 instance chaude (élimine les cold-starts)
# Coût supplémentaire : ~5 $/mois pour 1 instance min
gcloud run services update afa-api \
--region europe-west1 \
--min-instances 1 \
--max-instances 50
# CPU toujours alloué (pour background tasks ou WebSocket)
gcloud run services update afa-api \
--region europe-west1 \
--cpu-throttling=false # default: true (CPU coupé entre requêtes)
min-instances=1 sur la production élimine 99 % des cold-starts pour environ 5 $/mois. Sinon, viser un binaire de démarrage rapide (Go < 50 ms, Node.js Alpine 200-400 ms) et minimiser les imports lourds dans le module principal. Évitez d'établir des connexions DB au démarrage — utilisez du lazy init au premier appel.
Revisions, traffic splitting et déploiement canary
Chaque déploiement Cloud Run crée une revision immutable (afa-api-00001-abc, afa-api-00002-def...). Par défaut, 100 % du trafic bascule sur la nouvelle revision. Mais vous pouvez répartir le trafic entre plusieurs revisions pour faire du canary release ou du blue/green sans aucune infrastructure additionnelle.
Lister et inspecter les revisions
# Lister toutes les revisions d'un service
gcloud run revisions list \
--service afa-api \
--region europe-west1
# REVISION ACTIVE SERVICE DEPLOYED DEPLOYED BY
# afa-api-00003-xyz yes afa-api 2026-05-08 10:14 UTC user@example.com
# afa-api-00002-def no afa-api 2026-05-07 16:32 UTC user@example.com
# afa-api-00001-abc no afa-api 2026-05-06 11:00 UTC user@example.com
# Détails complets d'une revision
gcloud run revisions describe afa-api-00003-xyz \
--region europe-west1
Déploiement canary 10 / 90
# Étape 1 : déployer la nouvelle version SANS basculer le trafic
gcloud run deploy afa-api \
--source . \
--region europe-west1 \
--no-traffic \
--tag canary
# Étape 2 : router 10 % du trafic sur la canary, 90 % sur la stable
gcloud run services update-traffic afa-api \
--region europe-west1 \
--to-tags canary=10
# Tester la canary directement via son URL taggée :
# https://canary---afa-api-xxxxxxxxxx-ew.a.run.app
Promotion progressive ou rollback instantané
# Promotion à 50 % puis 100 %
gcloud run services update-traffic afa-api \
--region europe-west1 \
--to-tags canary=50
gcloud run services update-traffic afa-api \
--region europe-west1 \
--to-latest # 100 % sur la dernière revision
# Rollback IMMÉDIAT en cas d'incident (revert sur la revision précédente)
gcloud run services update-traffic afa-api \
--region europe-west1 \
--to-revisions afa-api-00002-def=100
Split multi-revisions complexe
# Répartition fine entre 3 revisions pour A/B testing
gcloud run services update-traffic afa-api \
--region europe-west1 \
--to-revisions \
afa-api-00003-xyz=70,\
afa-api-00004-abc=20,\
afa-api-00005-def=10
update-traffic --to-revisions répare en moins d'une seconde.
IAM least-privilege et Secret Manager
Par défaut, Cloud Run utilise le compte de service Compute Engine par défaut qui dispose du rôle roles/editor sur tout le projet — beaucoup trop permissif. La règle d'or sécurité GCP : créer un compte de service dédié par service Cloud Run, avec uniquement les rôles strictement nécessaires.
Créer un service account dédié
# Créer un compte de service avec un nom explicite
gcloud iam service-accounts create afa-api-sa \
--display-name="Compte de service Cloud Run AFA API" \
--description="Identité runtime du service afa-api"
# Adresse email résultante :
# afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com
# Accorder UNIQUEMENT les rôles nécessaires à ce service
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/secretmanager.secretAccessor"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"
Attacher le service account à Cloud Run
# Lier le service account au déploiement
gcloud run deploy afa-api \
--source . \
--region europe-west1 \
--service-account afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com \
--allow-unauthenticated
Stocker un secret dans Secret Manager
# Créer un secret (mot de passe DB par exemple)
echo -n "S3cr3t!P@ssw0rd2026" | \
gcloud secrets create db-password \
--data-file=- \
--replication-policy=automatic
# Ajouter une nouvelle version au secret existant (rotation)
echo -n "N3wP@ssw0rd2026" | \
gcloud secrets versions add db-password --data-file=-
# Lister les versions d'un secret
gcloud secrets versions list db-password
Injecter le secret dans Cloud Run
# Option A : injecter comme variable d'environnement (latest = version active)
gcloud run services update afa-api \
--region europe-west1 \
--update-secrets="DB_PASSWORD=db-password:latest"
# Option B : monter le secret comme fichier (utile pour les certs ou clés JSON)
gcloud run services update afa-api \
--region europe-west1 \
--update-secrets="/secrets/db-password=db-password:latest"
# Dans le code Node.js, lire les secrets injectés
# const dbPwd = process.env.DB_PASSWORD;
# ou : const dbPwd = require('fs').readFileSync('/secrets/db-password', 'utf8');
VPC Connector + Cloud SQL privé
# Étape 1 : créer un VPC Serverless Connector pour accéder au réseau privé
gcloud compute networks vpc-access connectors create afa-vpc-connector \
--region europe-west1 \
--range 10.8.0.0/28 \
--network default \
--min-instances 2 \
--max-instances 4 \
--machine-type e2-micro
# Étape 2 : créer une instance Cloud SQL PostgreSQL avec IP privée
gcloud sql instances create afa-postgres \
--database-version=POSTGRES_15 \
--region=europe-west1 \
--tier=db-f1-micro \
--network=default \
--no-assign-ip
# Étape 3 : connecter Cloud Run via le connector + Cloud SQL
gcloud run services update afa-api \
--region europe-west1 \
--vpc-connector afa-vpc-connector \
--vpc-egress all-traffic \
--add-cloudsql-instances $PROJECT_ID:europe-west1:afa-postgres
- Un service account par service Cloud Run (jamais le default)
- Bannir
roles/editoretroles/ownerpour les SA runtime - Toujours utiliser Secret Manager — jamais de secrets en clair dans
--set-env-vars - Auditer régulièrement avec
gcloud projects get-iam-policy $PROJECT_ID - Activer Cloud Audit Logs sur les modifications IAM (Data Access logs)
Cloud Build : pipeline CI/CD GitHub
Cloud Build est le service CI/CD natif de GCP. Il s'intègre directement à GitHub via une GitHub App officielle, déclenche un build à chaque push (ou PR), construit l'image, exécute les tests et déploie sur Cloud Run — le tout sans serveur Jenkins à maintenir. Le free tier offre 120 minutes de build par jour.
cloudbuild.yaml — pipeline complet
# cloudbuild.yaml — placé à la racine du repo Git
substitutions:
_SERVICE_NAME: afa-api
_REGION: europe-west1
_REPO: afa-services
steps:
# 1. Lint et tests unitaires
- id: 'install-and-test'
name: 'node:20-alpine'
entrypoint: 'sh'
args:
- '-c'
- |
npm ci
npm run lint
npm test
# 2. Build de l'image Docker
- id: 'build'
name: 'gcr.io/cloud-builders/docker'
args:
- 'build'
- '-t'
- '${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_SERVICE_NAME}:$SHORT_SHA'
- '-t'
- '${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_SERVICE_NAME}:latest'
- '.'
# 3. Push vers Artifact Registry
- id: 'push'
name: 'gcr.io/cloud-builders/docker'
args:
- 'push'
- '--all-tags'
- '${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_SERVICE_NAME}'
# 4. Déploiement Cloud Run avec canary 10%
- id: 'deploy-canary'
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
entrypoint: 'gcloud'
args:
- 'run'
- 'deploy'
- '${_SERVICE_NAME}'
- '--image=${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO}/${_SERVICE_NAME}:$SHORT_SHA'
- '--region=${_REGION}'
- '--no-traffic'
- '--tag=sha-$SHORT_SHA'
- '--service-account=afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com'
- '--update-secrets=DB_PASSWORD=db-password:latest'
# 5. Bascule progressive du trafic
- id: 'split-traffic'
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
entrypoint: 'gcloud'
args:
- 'run'
- 'services'
- 'update-traffic'
- '${_SERVICE_NAME}'
- '--region=${_REGION}'
- '--to-tags=sha-$SHORT_SHA=10'
# Stockage des logs de build
options:
logging: CLOUD_LOGGING_ONLY
machineType: E2_HIGHCPU_8
timeout: 1200s
Connecter le repo GitHub à Cloud Build
# Étape 1 : installer la GitHub App Cloud Build
# https://github.com/marketplace/google-cloud-build
# (autoriser sur le repo concerné)
# Étape 2 : créer le trigger en CLI
gcloud builds triggers create github \
--name="afa-api-deploy-on-main" \
--repo-name="afa-cloudrun-api" \
--repo-owner="angularforall" \
--branch-pattern="^main$" \
--build-config="cloudbuild.yaml" \
--description="Build et déploiement Cloud Run sur push main"
# Trigger avec PR (preview environment)
gcloud builds triggers create github \
--name="afa-api-pr-preview" \
--repo-name="afa-cloudrun-api" \
--repo-owner="angularforall" \
--pull-request-pattern="^main$" \
--build-config="cloudbuild-preview.yaml"
Permissions Cloud Build → Cloud Run
# Récupérer le numéro de projet (différent de l'ID texte)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
# Le service account Cloud Build a besoin de déployer sur Cloud Run
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/run.admin"
# Et de "voler" l'identité du service account runtime du service
gcloud iam service-accounts add-iam-policy-binding \
afa-api-sa@$PROJECT_ID.iam.gserviceaccount.com \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
google-github-actions/deploy-cloudrun@v2. Préférez cette voie si votre équipe a déjà standardisé sur GitHub Actions — vous gagnez la cohérence des workflows tout en utilisant Cloud Run comme cible. Le pipeline ci-dessus reste valable pour les équipes 100 % GCP-natives.
Monitoring, logs et custom domain
Cloud Run pousse automatiquement vers Cloud Logging tout ce qui sort sur stdout/stderr et alimente Cloud Monitoring avec des métriques natives (latence, requêtes, erreurs, instances actives). Aucun agent à installer, aucune config dans le container.
Consulter les logs en temps réel
# Stream des logs comme un tail -f distribué
gcloud run services logs tail afa-api \
--region europe-west1
# Filtrer les erreurs uniquement
gcloud logging read \
'resource.type=cloud_run_revision
AND resource.labels.service_name=afa-api
AND severity>=ERROR' \
--limit 50 \
--format json
# Logs structurés JSON — chaque champ devient indexable dans Cloud Logging
# Dans Node.js, écrire ainsi :
# console.log(JSON.stringify({ severity: 'INFO', userId: 42, action: 'login' }))
Créer une alerte Cloud Monitoring
# Politique d'alerte : taux d'erreur 5xx > 1 % sur 5 min
gcloud alpha monitoring policies create \
--notification-channels="projects/$PROJECT_ID/notificationChannels/CHAN_ID" \
--display-name="afa-api : taux 5xx élevé" \
--condition-display-name="5xx ratio > 1%" \
--condition-threshold-value=0.01 \
--condition-threshold-duration=300s \
--condition-filter='resource.type="cloud_run_revision"
AND resource.labels.service_name="afa-api"
AND metric.type="run.googleapis.com/request_count"
AND metric.labels.response_code_class="5xx"'
# Métriques natives disponibles sans aucune instrumentation :
# - request_count (nombre de requêtes par classe HTTP)
# - request_latencies (p50, p95, p99 en ms)
# - container/cpu/utilization
# - container/memory/utilization
# - container/instance_count
Custom domain via Cloud DNS
# Option 1 : Domain Mappings (le plus simple, gestion auto du certificat)
gcloud beta run domain-mappings create \
--service afa-api \
--domain api.angularforall.com \
--region europe-west1
# La commande retourne l'enregistrement DNS à ajouter chez votre registrar :
# Type: CNAME
# Name: api
# Value: ghs.googlehosted.com.
# Vérification (TLS via Let's Encrypt automatique sous 15-30 minutes)
gcloud beta run domain-mappings describe \
--domain api.angularforall.com \
--region europe-west1
Cloud DNS managé pour un domaine entier
# Créer une zone DNS dans Cloud DNS
gcloud dns managed-zones create angularforall-zone \
--description="Zone DNS pour angularforall.com" \
--dns-name="angularforall.com." \
--visibility=public
# Ajouter les enregistrements (transaction)
gcloud dns record-sets transaction start --zone=angularforall-zone
gcloud dns record-sets transaction add \
--zone=angularforall-zone \
--name="api.angularforall.com." \
--type=CNAME \
--ttl=300 \
"ghs.googlehosted.com."
gcloud dns record-sets transaction execute --zone=angularforall-zone
# Récupérer les nameservers à configurer chez votre registrar
gcloud dns managed-zones describe angularforall-zone \
--format="value(nameServers)"
# ns-cloud-a1.googledomains.com.
# ns-cloud-a2.googledomains.com.
# ns-cloud-a3.googledomains.com.
# ns-cloud-a4.googledomains.com.
Estimation de coûts mensuels
| Profil de service | Trafic mensuel | min-instances | Coût estimé |
|---|---|---|---|
| API hobby (free tier) | 1,5 M req | 0 | 0 $ (free tier) |
| Petite app SaaS B2B | 3 M req | 0 | ~ 5 $/mois |
| API prod sans cold-start | 10 M req | 1 | ~ 25 $/mois |
| API forte charge | 100 M req | 2 | ~ 180 $/mois |
- Service account dédié avec rôles least-privilege
- Tous les secrets dans Secret Manager (jamais en env vars en clair)
min-instances=1en prod pour éliminer les cold-starts critiques- Concurrency adaptée au runtime (Node.js : 80, Go : 250+)
- Health endpoint
/healthet probe configurée - Cloud Build trigger avec déploiement canary automatique
- Alertes Cloud Monitoring sur 5xx, latence p95 et instances max
- Custom domain mappé avec certificat Let's Encrypt auto-géré
- VPC Connector pour accès réseau privé (Cloud SQL, Memorystore)
- Logs structurés JSON pour exploitation dans Cloud Logging
Conclusion
Google Cloud Run est aujourd'hui l'une des plateformes serverless les plus pragmatiques du marché : un simple Dockerfile + une commande gcloud run deploy suffisent pour obtenir une API HTTPS auto-scalée, géo-redondée et facturée à la milliseconde. Le scale-to-zero combiné au free tier (2 millions de requêtes/mois) en fait un choix imbattable pour héberger des side-projects, des MVPs ou des microservices critiques.
En production, le combo gagnant tient en cinq pratiques : un service account dédié avec rôles least-privilege, des secrets dans Secret Manager, un déploiement canary 10/90 piloté par Cloud Build, un VPC Connector vers Cloud SQL pour l'isolation réseau, et un custom domain avec TLS auto-renouvelé. Le tout avec une expérience DevOps qui rivalise sans complexe avec AWS Lambda et Fargate, tout en offrant la flexibilité de n'importe quel container Docker.
- Toujours co-localiser Artifact Registry, Cloud Run et Cloud SQL dans la même région
- Utiliser des Dockerfiles multi-stage Alpine (image finale < 200 Mo)
- Préférer
--source .au début, puis passer à un pipeline Cloud Build versionné - Toujours tester la canary via son URL taggée avant de splitter le trafic
- Activer Cloud Audit Logs pour tracer les changements IAM
- Surveiller la métrique
container/instance_countpour détecter les emballements - Ne jamais déployer sans
--service-accountexplicite - Documenter les revisions importantes via les
--tag(ex :v1-2-0,hotfix-payment)