Diffuser du contenu dynamique et héberger des microservices avec Cloud Run

Associez Cloud Run à Firebase Hosting pour générer et diffuser votre du contenu dynamique ou de créer des API REST sous forme de microservices.

Avec Cloud Run, vous pouvez : déployer une application empaquetée dans une image de conteneur. Ensuite, à l'aide de Firebase Hosting, vous pouvez diriger les requêtes HTTPS application conteneurisée.

  • Cloud Run est compatible avec plusieurs langages (y compris Go, Node.js, Python et Java), ce qui vous permet d'utiliser le langage de programmation et le framework de votre choix.
  • Cloud Run effectue un scaling automatique et horizontal votre image de conteneur pour traiter les requêtes reçues, puis effectue un scaling à la baisse la demande diminue.
  • Vous ne payez que le CPU, la mémoire et le réseau utilisés lors du traitement des requêtes.

Exemples de cas d'utilisation et d'exemples pour Cloud Run intégré à Firebase Hosting, consultez notre Présentation de l'informatique sans serveur


Ce guide vous explique comment:

  1. Écrire une application Hello World simple
  2. Conteneuriser une application et l'importer dans Container Registry
  3. Déployer l'image de conteneur sur Cloud Run
  4. Diriger les requêtes Hosting vers votre application conteneurisée

Notez que pour améliorer les performances de la diffusion de contenu dynamique, vous pouvez éventuellement ajuster vos paramètres de cache.

Avant de commencer

Avant d'utiliser Cloud Run, vous devez effectuer certaines tâches initiales : y compris la configuration d'un compte Cloud Billing, l'activation du Cloud Run et installer l'outil de ligne de commande gcloud.

Configurer la facturation de votre projet

Cloud Run propose un quota d'utilisation sans frais, mais vous devez tout de même Compte Cloud Billing associé à votre projet Firebase afin d'utiliser ou d'essayer Cloud Run.

Activer l'API et installer le SDK

  1. Activez l'API Cloud Run dans la console des API Google:

    1. Ouvrez le Page de l'API Cloud Run dans la console d'API Google.

    2. Lorsque vous y êtes invité, sélectionnez votre projet Firebase.

    3. Cliquez sur Activer sur la page de l'API Cloud Run.

  2. Installez et initialisez Cloud SDK.

  3. Vérifiez que l'outil gcloud est configuré pour le bon projet:

    gcloud config list

Étape 1: Écrivez l'exemple d'application

Notez que Cloud Run prend en charge de nombreux autres langages en plus des langages présentés dans l'exemple suivant.

Accéder

  1. Créez un répertoire nommé helloworld-go, puis remplacez le répertoire par comme suit:

    mkdir helloworld-go
    cd helloworld-go
  2. Créez un fichier nommé helloworld.go, puis ajoutez le code suivant:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	log.Print("helloworld: received a request")
    	target := os.Getenv("TARGET")
    	if target == "" {
    		target = "World"
    	}
    	fmt.Fprintf(w, "Hello %s!\n", target)
    }
    
    func main() {
    	log.Print("helloworld: starting server...")
    
    	http.HandleFunc("/", handler)
    
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    
    	log.Printf("helloworld: listening on port %s", port)
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    

    Ce code crée un serveur Web de base qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée, et prête à être conteneurisée et importée dans Container Registry

Node.js

  1. Créez un répertoire nommé helloworld-nodejs, puis modifiez les sous-répertoires comme suit :

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Créez un fichier package.json avec le contenu suivant :

    {
      "name": "knative-serving-helloworld",
      "version": "1.0.0",
      "description": "Simple hello world sample in Node",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "express": "^4.20.0"
      }
    }
    
  3. Créez un fichier nommé index.js, puis ajoutez le code suivant:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      console.log('Hello world received a request.');
    
      const target = process.env.TARGET || 'World';
      res.send(`Hello ${target}!\n`);
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });
    

    Ce code crée un serveur Web de base qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée, et prête à être conteneurisée et importée dans Container Registry

Python

  1. Créez un répertoire nommé helloworld-python, puis modifiez les sous-répertoires comme suit :

    mkdir helloworld-python
    cd helloworld-python
  2. Créez un fichier nommé app.py, puis ajoutez le code suivant:

    import os
    
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        target = os.environ.get('TARGET', 'World')
        return 'Hello {}!\n'.format(target)
    
    if __name__ == "__main__":
        app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))
    

    Ce code crée un serveur Web de base qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée, et prête à être conteneurisée et importée dans Container Registry

Java

  1. Installez Java SE 8 ou une version ultérieure du JDK et CURL.

    Notez que cette opération n'est nécessaire que pour créer le projet Web dans l'étape suivante. Le Dockerfile, décrit plus tard, chargera tous les dépendances dans le conteneur.

  2. Depuis la console, créez un projet Web vide à l'aide de cURL, puis unzip:

    curl https://start.spring.io/starter.zip \
        -d dependencies=web \
        -d name=helloworld \
        -d artifactId=helloworld \
        -o helloworld.zip
    unzip helloworld.zip

    Un projet Spring Boot est créé.

  3. Mettez à jour la classe SpringBootApplication dans src/main/java/com/example/helloworld/HelloworldApplication.java par en ajoutant un @RestController pour gérer le mappage / et en ajoutant une @Value pour fournir la variable d'environnement TARGET:

    package com.example.helloworld;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    public class HelloworldApplication {
    
      @Value("${TARGET:World}")
      String target;
    
      @RestController
      class HelloworldController {
        @GetMapping("/")
        String hello() {
          return "Hello " + target + "!";
        }
      }
    
      public static void main(String[] args) {
        SpringApplication.run(HelloworldApplication.class, args);
      }
    }
    

    Ce code crée un serveur Web de base qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée, et prête à être conteneurisée et importée dans Container Registry

Étape 2: Conteneurisez une application et importez-la dans Container Registry

  1. Conteneuriser l'application exemple en créant un fichier nommé Dockerfile dans la dans le même répertoire que les fichiers sources. Copiez le contenu suivant dans votre .

    Accéder

    # Use the official Golang image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    FROM golang:latest as builder
    
    ARG TARGETOS
    ARG TARGETARCH
    
    # Create and change to the app directory.
    WORKDIR /app
    
    # Retrieve application dependencies using go modules.
    # Allows container builds to reuse downloaded dependencies.
    COPY go.* ./
    RUN go mod download
    
    # Copy local code to the container image.
    COPY . ./
    
    # Build the binary.
    # -mod=readonly ensures immutable go.mod and go.sum in container builds.
    RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -mod=readonly -v -o server
    
    # Use the official Alpine image for a lean production container.
    # https://hub.docker.com/_/alpine
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM alpine:3
    RUN apk add --no-cache ca-certificates
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /app/server /server
    
    # Run the web service on container startup.
    CMD ["/server"]
    

    Node.js

    # Use the official lightweight Node.js 12 image.
    # https://hub.docker.com/_/node
    FROM node:12-slim
    
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json are copied.
    # Copying this separately prevents re-running npm install on every code change.
    COPY package*.json ./
    
    # Install production dependencies.
    RUN npm install --only=production
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    Python

    # Use the official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.7-slim
    
    # Allow statements and log messages to immediately appear in the Knative logs
    ENV PYTHONUNBUFFERED True
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . ./
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Run the web service on container startup. Here we use the gunicorn
    # webserver, with one worker process and 8 threads.
    # For environments with multiple CPU cores, increase the number of workers
    # to be equal to the cores available.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 app:app
    

    Java

    # Use the official maven/Java 8 image to create a build artifact: https://hub.docker.com/_/maven
    FROM maven:3.5-jdk-8-alpine as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY pom.xml .
    COPY src ./src
    
    # Build a release artifact.
    RUN mvn package -DskipTests
    
    # Use the Official OpenJDK image for a lean production stage of our multi-stage build.
    # https://hub.docker.com/_/openjdk
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM openjdk:8-jre-alpine
    
    # Copy the jar to the production image from the builder stage.
    COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar
    
    # Run the web service on container startup.
    CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/helloworld.jar"]
    

  2. Créez votre image de conteneur à l'aide de Cloud Build en exécutant la commande suivante : à partir du répertoire contenant votre Dockerfile:

    gcloud builds submit --tag gcr.io/PROJECT_ID/helloworld

    En cas de réussite, un message Success (Opération réussie) contenant le nom de l'image (
    ) s'affiche. (gcr.io/PROJECT_ID/helloworld).

L'image du conteneur est désormais stockée dans Container Registry et peut être réutilisée si comme vous le souhaitez.

Notez qu'au lieu de Cloud Build, vous pouvez utiliser une version installée localement. de Docker pour créer votre conteneur localement.

Étape 3: Déployez l'image de conteneur dans Cloud Run

  1. Utilisez la commande suivante pour effectuer le déploiement :

    gcloud run deploy --image gcr.io/PROJECT_ID/helloworld

  2. Lorsque vous y êtes invité :

Pour des performances optimales, colocalisez votre service Cloud Run avec Hosting dans les régions suivantes:

  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1

Les réécritures vers Cloud Run à partir de Hosting sont prises en charge dans le dans les régions suivantes:

  • asia-east1
  • asia-east2
  • asia-northeast1
  • asia-northeast2
  • asia-northeast3
  • asia-south1
  • asia-south2
  • asia-southeast1
  • asia-southeast2
  • australia-southeast1
  • australia-southeast2
  • europe-central2
  • europe-north1
  • europe-southwest1
  • europe-west1
  • europe-west12
  • europe-west2
  • europe-west3
  • europe-west4
  • europe-west6
  • europe-west8
  • europe-west9
  • me-central1
  • me-west1
  • northamerica-northeast1
  • northamerica-northeast2
  • southamerica-east1
  • southamerica-west1
  • us-central1
  • us-east1
  • us-east4
  • us-east5
  • us-south1
  • us-west1
  • us-west2
  • us-west3
  • us-west4
  • us-west1
  • us-central1
  • us-east1
  • europe-west1
  • asia-east1
  1. Attendez que le déploiement se termine. En cas de réussite, la ligne de commande affiche l'URL du service. Par exemple : https://helloworld-RANDOM_HASH-us-central1.a.run.app

  2. Accédez à votre conteneur déployé en ouvrant l'URL du service dans un navigateur Web.

L'étape suivante vous explique comment accéder à cette application conteneurisée à partir d'un Firebase Hosting de destination pour qu'il puisse générer du contenu dynamique pour votre site hébergé par Firebase.

Étape 4:Diriger les demandes d'hébergement vers votre application conteneurisée

Les règles de réécriture vous permettent de diriger les requêtes correspondant à des modèles spécifiques vers une seule destination.

L'exemple suivant montre comment diriger toutes les requêtes depuis la page /helloworld sur votre site Hosting pour déclencher le démarrage et l'exécution de votre instance de conteneur helloworld.

  1. Vérifiez les points suivants :

    Pour obtenir des instructions détaillées sur l'installation de la CLI et l'initialisation Hosting, consultez les Guide de démarrage pour Hosting

  2. Ouvrez le fichier firebase.json.

  3. Ajoutez la configuration rewrite suivante dans la section hosting:

    "hosting": {
      // ...
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "/helloworld",
        "run": {
          "serviceId": "helloworld",  // "service name" (from when you deployed the container image)
          "region": "us-central1",    // optional (if omitted, default is us-central1)
          "pinTag": true              // optional (see note below)
        }
      } ]
    }
  4. Déployez votre configuration d'hébergement sur votre site en exécutant la commande suivante : à la racine du répertoire de votre projet:

    firebase deploy --only hosting

Votre conteneur est désormais accessible via les URL suivantes:

  • Vos sous-domaines Firebase:
    PROJECT_ID.web.app/ et PROJECT_ID.firebaseapp.com/

  • Domaines personnalisés connectés :
    CUSTOM_DOMAIN/

Pour en savoir plus sur les règles de réécriture, consultez la page de configuration de Hosting. Vous pouvez vous découvrirez aussi ordre de priorité des réponses pour différentes configurations Hosting.

Tester en local

Pendant le développement, vous pouvez exécuter et tester votre image de conteneur localement. Pour des instructions détaillées, consultez le Documentation sur Cloud Run

Étapes suivantes