Offri contenuti dinamici e ospita microservizi con Cloud Run

Associa Cloud Run a Firebase Hosting per generare e servire i tuoi contenuti dinamici o creare API REST come microservizi.

Utilizzando Cloud Run , puoi eseguire il deploy di un'applicazione inclusa in un'immagine container. Quindi, utilizzando Firebase Hosting, puoi indirizzare le richieste HTTPS per attivare la tua app containerizzata.

  • Cloud Run supporta diversi linguaggi (tra cui Go, Node.js, Python e Java), offrendoti la flessibilità di utilizzare il linguaggio di programmazione e il framework che preferisci.
  • Cloud Run ridimensiona automaticamente e orizzontalmente l'immagine del contenitore per gestire le richieste ricevute, quindi la ridimensiona quando la domanda diminuisce.
  • Paghi solo per la CPU, la memoria e la rete consumate durante la gestione delle richieste.

Per esempi di casi d'uso ed esempi per Cloud Run integrato con Firebase Hosting, visita la nostra panoramica sul serverless .


Questa guida ti mostra come:

  1. Scrivi una semplice applicazione Hello World
  2. Containerizza un'app e caricala su Container Registry
  3. Distribuisci l'immagine del contenitore a Cloud Run
  4. Richieste di hosting dirette alla tua app containerizzata

Tieni presente che per migliorare le prestazioni della fornitura di contenuti dinamici, puoi facoltativamente ottimizzare le impostazioni della cache .

Prima di iniziare

Prima di utilizzare Cloud Run, devi completare alcune attività iniziali, tra cui la configurazione di un account di fatturazione Cloud, l'abilitazione dell'API Cloud Run e l'installazione dello strumento a riga di comando gcloud .

Imposta la fatturazione per il tuo progetto

Cloud Run offre una quota di utilizzo gratuita , ma devi comunque avere un account di fatturazione Cloud associato al tuo progetto Firebase per utilizzare o provare Cloud Run.

Abilita l'API e installa l'SDK

  1. Abilita l'API Cloud Run nella console delle API di Google:

    1. Apri la pagina dell'API Cloud Run nella console delle API di Google.

    2. Quando richiesto, seleziona il tuo progetto Firebase.

    3. Fai clic su Abilita nella pagina API Cloud Run.

  2. Installa e inizializza Cloud SDK.

  3. Verifica che lo strumento gcloud sia configurato per il progetto corretto:

    gcloud config list

Passaggio 1 : scrivere l'applicazione di esempio

Tieni presente che Cloud Run supporta molte altre lingue oltre a quelle mostrate nell'esempio seguente.

Andare

  1. Crea una nuova directory denominata helloworld-go , quindi modifica la directory al suo interno:

    mkdir helloworld-go
    cd helloworld-go
  2. Crea un nuovo file denominato helloworld.go , quindi aggiungi il seguente codice:

    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))
    }
    

    Questo codice crea un server Web di base in ascolto sulla porta definita dalla variabile di ambiente PORT .

La tua app è completata e pronta per essere inserita in un contenitore e caricata su Container Registry.

Node.js

  1. Crea una nuova directory denominata helloworld-nodejs , quindi modifica la directory al suo interno:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Crea un file package.json con il seguente contenuto:

    {
      "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.18.2"
      }
    }
    
  3. Crea un nuovo file denominato index.js , quindi aggiungi il seguente codice:

    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);
    });
    

    Questo codice crea un server Web di base in ascolto sulla porta definita dalla variabile di ambiente PORT .

La tua app è completata e pronta per essere inserita in un contenitore e caricata su Container Registry.

Pitone

  1. Crea una nuova directory denominata helloworld-python , quindi modifica la directory al suo interno:

    mkdir helloworld-python
    cd helloworld-python
  2. Crea un nuovo file denominato app.py , quindi aggiungi il seguente codice:

    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)))
    

    Questo codice crea un server Web di base in ascolto sulla porta definita dalla variabile di ambiente PORT .

La tua app è completata e pronta per essere inserita in un contenitore e caricata su Container Registry.

Giava

  1. Installa Java SE 8 o versioni successive JDK e CURL .

    Tieni presente che dobbiamo farlo solo per creare il nuovo progetto web nel passaggio successivo. Il Dockerfile, descritto più avanti, caricherà tutte le dipendenze nel contenitore.

  2. Dalla console, crea un nuovo progetto web vuoto utilizzando cURL quindi decomprimi i comandi:

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

    Questo crea un progetto SpringBoot.

  3. Aggiorna la classe SpringBootApplication in src/main/java/com/example/helloworld/HelloworldApplication.java aggiungendo un @RestController per gestire la mappatura / e aggiungi anche un campo @Value per fornire la variabile di ambiente 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);
      }
    }
    

    Questo codice crea un server Web di base in ascolto sulla porta definita dalla variabile di ambiente PORT .

La tua app è completata e pronta per essere inserita in un contenitore e caricata su Container Registry.

Passaggio 2 : containerizza un'app e caricala su Container Registry

  1. Containerizza l'app di esempio creando un nuovo file denominato Dockerfile nella stessa directory dei file di origine. Copia il seguente contenuto nel tuo file.

    Andare

    # 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" ]
    

    Pitone

    # 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
    

    Giava

    # 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. Crea l'immagine del tuo contenitore utilizzando Cloud Build eseguendo il comando seguente dalla directory contenente il tuo Dockerfile:

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

    In caso di successo, vedrai un messaggio di SUCCESSO contenente il nome dell'immagine
    ( gcr.io/ PROJECT_ID /helloworld ).

L'immagine del contenitore è ora archiviata in Container Registry e, se lo si desidera, può essere riutilizzata.

Tieni presente che, invece di Cloud Build, puoi utilizzare una versione di Docker installata localmente per creare il tuo contenitore localmente .

Passaggio 3 : distribuisci l'immagine del contenitore su Cloud Run

  1. Distribuisci utilizzando il seguente comando:

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

  2. Quando richiesto:

Per ottenere le migliori prestazioni, colloca il tuo servizio Cloud Run con l'hosting utilizzando le seguenti regioni:

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

Le riscritture su Cloud Run dall'hosting sono supportate nelle seguenti regioni:

  • 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. Attendi qualche istante per il completamento della distribuzione. In caso di successo, la riga di comando visualizza l'URL del servizio. Ad esempio https://helloworld- RANDOM_HASH -us-central1.a.run.app

  2. Visita il tuo contenitore distribuito aprendo l'URL del servizio in un browser web.

Il passaggio successivo ti illustra come accedere a questa app containerizzata da un URL di hosting Firebase in modo che possa generare contenuto dinamico per il tuo sito ospitato su Firebase.

Passaggio 4: indirizza le richieste di hosting alla tua app containerizzata

Con le regole di riscrittura , puoi indirizzare le richieste che corrispondono a modelli specifici a un'unica destinazione.

L'esempio seguente mostra come indirizzare tutte le richieste dalla pagina /helloworld sul tuo sito di hosting per attivare l'avvio e l'esecuzione della tua istanza di contenitore helloworld .

  1. Assicurati che:

    Per istruzioni dettagliate sull'installazione della CLI e sull'inizializzazione dell'hosting, consultare la guida introduttiva per l'hosting .

  2. Apri il file firebase.json .

  3. Aggiungi la seguente configurazione rewrite nella sezione 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. Distribuisci la configurazione di hosting sul tuo sito eseguendo il seguente comando dalla radice della directory del progetto:

    firebase deploy --only hosting

Il tuo contenitore è ora raggiungibile tramite i seguenti URL:

  • I tuoi sottodomini Firebase:
    PROJECT_ID .web.app/ e PROJECT_ID .firebaseapp.com/

  • Eventuali domini personalizzati collegati:
    CUSTOM_DOMAIN /

Visita la pagina di configurazione dell'hosting per maggiori dettagli sulle regole di riscrittura . Puoi anche conoscere l' ordine di priorità delle risposte per varie configurazioni di Hosting.

Prova localmente

Durante lo sviluppo, puoi eseguire e testare l'immagine del contenitore localmente. Per istruzioni dettagliate, consulta la documentazione di Cloud Run .

Prossimi passi