Dynamische Inhalte bereitstellen und Mikrodienste mit Cloud Run hosten

Verknüpfen Sie Cloud Run mit Firebase Hosting, um dynamische Inhalte zu generieren und bereitzustellen oder REST APIs als Mikrodienste zu erstellen.

Mit Cloud Run können Sie eine in einem Container-Image verpackte Anwendung bereitstellen. Mit Firebase Hosting können Sie dann HTTPS-Anfragen weiterleiten, um Ihre containerisierte App auszulösen.

Beispiele für Anwendungsfälle und Beispiele für Cloud Run in Kombination mit Firebase Hosting, finden Sie in unserer Übersicht zu serverlosen Diensten.


In dieser Anleitung erfahren Sie, wie Sie Folgendes tun:

  1. Eine einfache Hello World-Anwendung schreiben
  2. Eine App containerisieren und in Artifact Registry hochladen
  3. Das Container-Image in Cloud Run bereitstellen
  4. Hosting-Anfragen an Ihre containerisierte App weiterleitenHosting

Hinweis: Sie können optional Ihre Cache-Einstellungen optimieren, um die Leistung bei der Bereitstellung dynamischer Inhalte zu verbessern.

Hinweis

Bevor Sie Cloud Run verwenden können, müssen Sie einige erste Schritte ausführen, z. B. ein Cloud Billing Konto einrichten, die Cloud Run API aktivieren und das gcloud Befehlszeilentool installieren.

Abrechnung für Ihr Projekt einrichten

Cloud Run bietet ein kostenloses Nutzungskontingent, Sie benötigen jedoch ein Cloud Billing-Konto, das mit Ihrem Firebase-Projekt verknüpft ist, um Cloud Run zu verwenden oder auszuprobieren.

API aktivieren und SDK installieren

  1. Aktivieren Sie die Cloud Run API in der Google APIs Console:

    1. Öffnen Sie die Cloud Run API-Seite in der Google APIs Console.

    2. Wählen Sie Ihr Firebase-Projekt aus, wenn Sie dazu aufgefordert werden.

    3. Klicken Sie auf der Seite „Cloud Run API“ auf Aktivieren.

  2. Installieren und initialisieren Sie das Cloud SDK.

  3. Prüfen Sie, ob das gcloud-Tool für das richtige Projekt konfiguriert ist:

    gcloud config list

Schritt 1: Beispielanwendung schreiben

Beachten Sie, dass Cloud Run zusätzlich zu den im folgenden Beispiel gezeigten Sprachen viele andere Sprachen unterstützt.

Go

  1. Erstellen Sie ein neues Verzeichnis mit dem Namen helloworld-go und wechseln Sie dann in dieses Verzeichnis:

    mkdir helloworld-go
    cd helloworld-go
  2. Erstellen Sie eine neue Datei mit dem Namen helloworld.go und fügen Sie den folgenden Code hinzu:

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

    Mit diesem Code wird ein einfacher Webserver erstellt, der den von der Umgebungsvariable PORT definierten Port überwacht.

Die Anwendung ist jetzt fertig und kann containerisiert und dann in Artifact Registry hochgeladen werden.

Node.js

  1. Erstellen Sie ein neues Verzeichnis mit dem Namen helloworld-nodejs und wechseln Sie dann in dieses Verzeichnis:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Erstellen Sie eine package.json-Datei mit folgendem Inhalt:

    {
      "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.22.1"
      }
    }
    
  3. Erstellen Sie eine neue Datei mit dem Namen index.js und fügen Sie den folgenden Code hinzu:

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

    Mit diesem Code wird ein einfacher Webserver erstellt, der den von der Umgebungsvariable PORT definierten Port überwacht.

Die Anwendung ist jetzt fertig und kann containerisiert und dann in Artifact Registry hochgeladen werden.

Python

  1. Erstellen Sie ein neues Verzeichnis mit dem Namen helloworld-python und wechseln Sie dann in dieses Verzeichnis:

    mkdir helloworld-python
    cd helloworld-python
  2. Erstellen Sie eine neue Datei mit dem Namen app.py und fügen Sie den folgenden Code hinzu:

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

    Mit diesem Code wird ein einfacher Webserver erstellt, der den von der Umgebungsvariable PORT definierten Port überwacht.

Die Anwendung ist jetzt fertig und kann containerisiert und dann in Artifact Registry hochgeladen werden.

Java

  1. Installieren Sie das Java SE Development Kit Version 8 oder höher und CURL.

    Dies ist nur erforderlich, damit wir im nächsten Schritt das neue Webprojekt erstellen können. Das weiter unten beschriebene Dockerfile wird dann später alle Abhängigkeiten in den Container laden.

  2. Erstellen Sie über die Konsole mit den Befehlen „cURL“ und „unzip“ ein neues, leeres Webprojekt:

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

    Dadurch wird ein SpringBoot-Projekt erstellt.

  3. Aktualisieren Sie die SpringBootApplication Klasse in src/main/java/com/example/helloworld/HelloworldApplication.java durch Hinzufügen eines @RestController zur Verarbeitung der / Zuordnung und fügen Sie auch ein @Value Feld hinzu, um die TARGET Umgebungsvariable bereitzustellen:

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

    Mit diesem Code wird ein einfacher Webserver erstellt, der den von der Umgebungsvariable PORT definierten Port überwacht.

Die Anwendung ist jetzt fertig und kann containerisiert und dann in Artifact Registry hochgeladen werden.

Schritt 2: Eine App containerisieren und in Artifact Registry hochladen

  1. Erstellen Sie zum Containerisieren der Beispielanwendung in dem Verzeichnis, in dem sich die Quelldateien befinden, eine neue Datei namens Dockerfile. Kopieren Sie den folgenden Inhalt in die Datei.

    Go

    # 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
    
    # Copy local code to the container image.
    COPY . ./
    
    # Install dependencies and tidy up the go.mod and go.sum files.
    RUN go mod tidy
    
    # 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. Erstellen Sie das Container-Image mit Cloud Build. Dazu führen Sie folgenden Befehl in dem Verzeichnis aus, in dem sich das Dockerfile befindet:

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

    Bei Erfolg wird eine SUCCESS-Meldung mit dem Image-Namen
    (gcr.io/PROJECT_ID/helloworld) angezeigt.

Das Container-Image wird jetzt in Artifact Registry gespeichert und kann bei Bedarf wiederverwendet werden.

Anstelle von Cloud Build können Sie auch eine lokal installierte Version von Docker verwenden, um den Container lokal zu erstellen.

Schritt 3: Container-Image in Cloud Run bereitstellen

  1. Stellen Sie es mit dem folgenden Befehl bereit:

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

  2. Tun Sie Folgendes, wenn Sie dazu aufgefordert werden:

    • Wählen Sie eine Region aus, z. B. us-central1.
    • Bestätigen Sie den Dienstnamen, z. B. helloworld.
    • Antworten Sie mit Y auf allow unauthenticated invocations (nicht authentifizierte Aufrufe zulassen).
  3. Warten Sie einige Sekunden, bis die Bereitstellung abgeschlossen ist. Bei Erfolg wird in der Befehlszeile die Dienst-URL angezeigt. Beispiel: https://helloworld-RANDOM_HASH-us-central1.a.run.app

  4. Rufen Sie den bereitgestellten Container auf. Dazu öffnen Sie in einem Webbrowser die Dienst-URL.

Im nächsten Schritt erfahren Sie, wie Sie auf diese containerisierte App über eine Firebase Hosting URL zugreifen können, damit sie dynamische Inhalte für Ihre auf Firebase gehostete Website generieren kann.

Schritt 4:Hosting-Anfragen an Ihre containerisierte App weiterleiten

Mit Umschreibungsregeln können Sie Anfragen , die bestimmten Mustern entsprechen, an ein einzelnes Ziel weiterleiten.

Im folgenden Beispiel wird gezeigt, wie Sie alle Anfragen von der Seite /helloworld auf Ihrer Hosting Website weiterleiten, um den Start und die Ausführung von Ihrer helloworld Containerinstanz auszulösen.

  1. Sie müssen Folgendes sicherstellen:

    Eine detaillierte Anleitung zur Installation der CLI und zur Initialisierung Hosting finden Sie im Leitfaden Erste Schritte mit Hosting.

  2. Öffnen Sie die Datei firebase.json.

  3. Fügen Sie unter dem Abschnitt hosting die folgende rewrite-Konfiguration hinzu:

    "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. Stellen Sie Ihre Hosting-Konfiguration auf Ihrer Website bereit. Führen Sie dazu den folgenden Befehl im Stammverzeichnis Ihres Projektverzeichnisses aus:

    firebase deploy --only hosting

Ihr Container ist jetzt über die folgenden URLs erreichbar:

  • Ihre Firebase-Subdomains:
    PROJECT_ID.web.app/ und PROJECT_ID.firebaseapp.com/

  • Alle verbundenen benutzerdefinierten Domains:
    CUSTOM_DOMAIN/

Weitere Informationen zu Umschreibungsregeln finden Sie auf der Hosting Konfigurationsseite für mehr Details. Sie können sich auch über die Prioritätsreihenfolge von Antworten für verschiedene Hosting Konfigurationen informieren.

Lokal testen

Während der Entwicklung haben Sie die Möglichkeit, das Container-Image lokal auszuführen und zu testen. Eine detaillierte Anleitung finden Sie in der Cloud Run Dokumentation.

Nächste Schritte