Obsługa treści dynamicznych i hostowanie mikroserwisów za pomocą Cloud Run

Połącz Cloud Run z parametrem Firebase Hosting, aby wygenerować i wyświetlać dynamiczne treści lub tworzenie interfejsów REST API jako mikroserwisów.

Dzięki Cloud Run możesz: wdrożysz aplikację spakowaną do obrazu kontenera. Następnie za pomocą Firebase Hosting możesz kierować żądania HTTPS, aby wywołać aplikację w kontenerze.

  • Cloud Run obsługuje kilka języków (w tym Go, Node.js, Python i Java), co daje Ci możliwość używania wybranego języka programowania i ramy.
  • Cloud Run automatycznie i w poziomie obrazu kontenera w celu obsługi otrzymanych żądań, a następnie skaluje się w dół, maleje popyt.
  • Płacisz tylko za procesor, pamięć i sieć wykorzystywane w trakcie obsługiwania żądań.

Przykładowe przypadki użycia i przykłady dotyczące platformy Cloud Run zintegrowanej z Firebase Hosting, odwiedź Omówienie technologii bezserwerowych.


Z tego przewodnika dowiesz się, jak:

  1. Tworzenie prostej aplikacji Hello World
  2. Konteneryzowanie aplikacji i przesyłanie jej do Container Registry
  3. Wdróż obraz kontenera w środowisku Cloud Run
  4. Kierowanie żądań Hosting do aplikacji skonteneryzowanej

Pamiętaj, że aby poprawić wydajność wyświetlania treści dynamicznej, możesz: (opcjonalnie) dostosuj ustawienia pamięci podręcznej.

Zanim zaczniesz

Zanim zaczniesz używać usługi Cloud Run, musisz wykonać pewne zadania wstępne. między innymi przez skonfigurowanie konta Cloud Billing czy włączenie funkcji Cloud Run API i zainstalowanie narzędzia wiersza poleceń gcloud.

Skonfiguruj rozliczenia w projekcie

Cloud Run oferuje bezpłatny limit wykorzystania, ale i tak musisz mieć Cloud Billing konto powiązane z projektem Firebase, aby używać lub wypróbować usługę Cloud Run.

Włącz interfejs API i zainstaluj pakiet SDK

  1. Włącz interfejs API Cloud Run w konsoli interfejsów API Google:

    1. Otwórz aplikację Strona interfejsu API Cloud Run w konsoli interfejsów API Google.

    2. Gdy pojawi się taka prośba, wybierz projekt Firebase.

    3. Kliknij Włącz na stronie interfejsu API Cloud Run.

  2. Zainstaluj i zainicjuj pakietu SDK Cloud.

  3. Sprawdź, czy narzędzie gcloud jest skonfigurowane dla właściwego projektu:

    gcloud config list

Krok 1. Napisz przykładową aplikację

Pamiętaj, że Cloud Run obsługuje wiele innych języków oprócz języków wymienionych w poniższym przykładzie.

Go

  1. Utwórz nowy katalog o nazwie helloworld-go, a następnie zmień katalog na :

    mkdir helloworld-go
    cd helloworld-go
  2. Utwórz nowy plik o nazwie helloworld.go i dodaj do niego ten kod:

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

    Ten kod tworzy podstawowy serwer WWW, który nasłuchuje na porcie określonym przez zmienną środowiskową PORT.

Aplikacja jest gotowa i możesz ją teraz skonteneryzować i przesłać do Container Registry.

Node.js

  1. Utwórz nowy katalog o nazwie helloworld-nodejs, a następnie zmień katalog w nim:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Utwórz plik package.json z tą zawartością:

    {
      "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. Utwórz nowy plik o nazwie index.js, a następnie dodaj ten kod:

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

    Ten kod tworzy podstawowy serwer WWW, który nasłuchuje na porcie określonym przez zmienną środowiskową PORT.

Aplikacja jest gotowa i możesz ją teraz skonteneryzować i przesłać do: Container Registry

Python

  1. Utwórz nowy katalog o nazwie helloworld-python, a następnie zmień katalog w nim:

    mkdir helloworld-python
    cd helloworld-python
  2. Utwórz nowy plik o nazwie app.py, a następnie dodaj ten kod:

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

    Ten kod tworzy podstawowy serwer WWW, który nasłuchuje na porcie określonym przez zmienną środowiskową PORT.

Aplikacja jest gotowa i możesz ją teraz skonteneryzować i przesłać do: Container Registry

Java

  1. Zainstaluj Java SE 8 lub nowszej JDK i CURL.

    Pamiętaj, że jest to konieczne tylko do utworzenia nowego projektu internetowego w kolejny krok. Plik Dockerfile, którego opis znajdziesz poniżej, wczyta wszystkie zależności do kontenera.

  2. W konsoli utwórz nowy, pusty projekt internetowy przy użyciu polecenia cURL, a następnie polecenia rozpakowywania:

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

    Spowoduje to utworzenie projektu SpringBoot.

  3. Zaktualizuj klasę SpringBootApplicationsrc/main/java/com/example/helloworld/HelloworldApplication.java, dodając element @RestController do obsługi mapowania /, a także pole @Value do podawania zmiennej środowiskowej 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);
      }
    }
    

    Ten kod tworzy podstawowy serwer WWW, który nasłuchuje na porcie określonym przez zmienną środowiskową PORT.

Aplikacja jest gotowa i możesz ją teraz skonteneryzować i przesłać do Container Registry.

Krok 2. Umieść aplikację w kontenerze i prześlij ją do Container Registry

  1. Skonteneryzujesz przykładową aplikację, tworząc nowy plik o nazwie Dockerfile w w tym samym katalogu co pliki źródłowe. Skopiuj do pliku te treści.

    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
    
    # 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. Utwórz obraz kontenera za pomocą narzędzia Cloud Build, uruchamiając to polecenie w katalogu zawierającym plik Dockerfile:

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

    Gdy zakończy się pomyślnie, wyświetli się komunikat z informacją o udanym przeprowadzeniu operacji i nazwą obrazu.
    (gcr.io/PROJECT_ID/helloworld).

Obraz kontenera jest teraz przechowywany w usłudze Container Registry i można go użyć ponownie, jeśli pożądaną.

Pamiętaj, że zamiast Cloud Build możesz użyć wersji zainstalowanej lokalnie. Dockera, aby Utwórz kontener lokalnie.

Krok 3. Wdróż obraz kontenera w środowisku Cloud Run

  1. Wdróż za pomocą tego polecenia:

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

  2. Gdy pojawi się komunikat:

Aby uzyskać najlepszą wydajność, kolokuj usługę Cloud Run z Hosting, korzystając z tych regionów:

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

Przepisywanie na Cloud Run z: Hosting jest obsługiwane w te regiony:

  • 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. Poczekaj chwilę na zakończenie wdrażania. Kiedy operacja zostanie wykonana, wyświetla adres URL usługi. Na przykład: https://helloworld-RANDOM_HASH-us-central1.a.run.app

  2. Przejdź do wdrożonego kontenera, otwierając adres URL usługi w przeglądarce.

W następnym kroku dowiesz się, jak uzyskać dostęp do tej skonteneryzowanej aplikacji z poziomu Firebase Hosting, aby mógł generować treści dynamiczne Witryna hostowana w Firebase.

Krok 4. Przekierowuj żądania hostingu do aplikacji w kontenerze

Na reguły przepisywania, możesz kierować żądania pasujące do określonych wzorców w jednym miejscu docelowym.

Przykład poniżej pokazuje, jak kierować wszystkie żądania ze strony /helloworld w witrynie Hosting, aby uruchomić i uruchomić instancji kontenera helloworld.

  1. Sprawdź, czy:

    Szczegółowe instrukcje instalowania i inicjowania interfejsu wiersza poleceń Hosting, zobacz Przewodnik dla początkujących – Hosting.

  2. Otwórz plik firebase.json.

  3. W sekcji hosting dodaj tę konfigurację rewrite:

    "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. Wdróż konfigurację hostingu w swojej witrynie, uruchamiając to polecenie w katalogu głównym projektu:

    firebase deploy --only hosting

Twój kontener jest teraz dostępny pod tymi adresami URL:

  • Twoje subdomeny Firebase:
    PROJECT_ID.web.app/ i PROJECT_ID.firebaseapp.com/

  • Wszystkie połączone domeny niestandardowe:
    CUSTOM_DOMAIN/

Otwórz stronę konfiguracji usługi Hosting dla: dowiedz się więcej o regułach przepisywania. Możesz też dowiedzieć się więcej o kolejności priorytetów odpowiedzi w różnych konfiguracjach Hosting.

Przetestuj lokalnie

Podczas tworzenia możesz uruchomić i przetestować obraz kontenera lokalnie. Dla: szczegółowe instrukcje znajdziesz w dokumentacja Cloud Run.

Dalsze kroki