ให้บริการเนื้อหาแบบไดนามิกและไมโครเซอร์วิสโฮสต์ด้วย Cloud Run

จับคู่ Cloud Run กับ Firebase Hosting เพื่อสร้างและให้บริการเนื้อหาไดนามิกของคุณ หรือสร้าง REST API เป็นไมโครเซอร์วิส

เมื่อใช้ Cloud Run คุณจะปรับใช้แอปพลิเคชันที่แพ็กเกจในคอนเทนเนอร์อิมเมจได้ จากนั้น เมื่อใช้ Firebase Hosting คุณจะส่งคำขอ HTTPS เพื่อทริกเกอร์แอปที่มีคอนเทนเนอร์ได้

ตัวอย่างเช่น กรณีการใช้งานและตัวอย่างสำหรับ Cloud Run ที่ผสานรวมกับโฮสติ้ง Firebase โปรดไปที่ ภาพรวมแบบไร้เซิร์ฟเวอร์ ของเรา


คู่มือนี้จะแสดงวิธีการ:

  1. เขียนแอปพลิเคชัน Hello World ง่ายๆ
  2. สร้างคอนเทนเนอร์แอปและอัปโหลดไปยัง Container Registry
  3. ทำให้อิมเมจคอนเทนเนอร์ใช้งานได้กับ Cloud Run
  4. คำขอโฮสติ้งโดยตรงไปยังแอปคอนเทนเนอร์ของคุณ

โปรดทราบว่าเพื่อปรับปรุงประสิทธิภาพการแสดงเนื้อหาแบบไดนามิก คุณสามารถเลือกปรับแต่ง การตั้งค่าแคช ของคุณได้

ก่อนที่คุณจะเริ่ม

ก่อนที่จะใช้ Cloud Run คุณต้องทำงานเบื้องต้นบางอย่างให้เสร็จสิ้น รวมถึงการตั้งค่าบัญชี Cloud Billing, เปิดใช้ Cloud Run API และติดตั้งเครื่องมือบรรทัดคำสั่ง gcloud

ตั้งค่าการเรียกเก็บเงินสำหรับโครงการของคุณ

Cloud Run เสนอ โควต้าการใช้งานฟรี แต่คุณยังคงต้องมี บัญชีสำหรับการเรียกเก็บเงิน Cloud ที่เชื่อมโยงกับโปรเจ็กต์ Firebase ของคุณเพื่อใช้หรือลองใช้ Cloud Run

เปิดใช้งาน API และติดตั้ง SDK

  1. เปิดใช้งาน Cloud Run API ในคอนโซล Google APIs:

    1. เปิด หน้า Cloud Run API ในคอนโซล Google API

    2. เมื่อได้รับแจ้ง ให้เลือกโปรเจ็กต์ Firebase ของคุณ

    3. คลิก เปิดใช้งาน ในหน้า Cloud Run API

  2. ติดตั้งและเริ่มต้น Cloud SDK

  3. ตรวจสอบว่าเครื่องมือ gcloud ได้รับการกำหนดค่าสำหรับโปรเจ็กต์ที่ถูกต้อง:

    gcloud config list

ขั้นตอนที่ 1 : เขียนแอปพลิเคชันตัวอย่าง

โปรดทราบว่า Cloud Run รองรับ ภาษาอื่นๆ มากมาย นอกเหนือจากภาษาที่แสดงในตัวอย่างต่อไปนี้

ไป

  1. สร้างไดเร็กทอรีใหม่ชื่อ helloworld-go จากนั้นเปลี่ยนไดเร็กทอรีเป็น:

    mkdir helloworld-go
    cd helloworld-go
  2. สร้างไฟล์ใหม่ชื่อ helloworld.go จากนั้นเพิ่มโค้ดต่อไปนี้:

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

    รหัสนี้สร้างเว็บเซิร์ฟเวอร์พื้นฐานที่รับฟังพอร์ตที่กำหนดโดยตัวแปรสภาพแวดล้อม PORT

แอปของคุณเสร็จสมบูรณ์และพร้อมที่จะบรรจุลงในคอนเทนเนอร์และอัปโหลดไปยัง Container Registry

โหนด js

  1. สร้างไดเร็กทอรีใหม่ชื่อ helloworld-nodejs จากนั้นเปลี่ยนไดเร็กทอรีเป็น:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. สร้างไฟล์ package.json โดยมีเนื้อหาดังต่อไปนี้:

    {
      "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. สร้างไฟล์ใหม่ชื่อ index.js จากนั้นเพิ่มโค้ดต่อไปนี้:

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

    รหัสนี้สร้างเว็บเซิร์ฟเวอร์พื้นฐานที่รับฟังพอร์ตที่กำหนดโดยตัวแปรสภาพแวดล้อม PORT

แอปของคุณเสร็จสมบูรณ์และพร้อมที่จะบรรจุลงในคอนเทนเนอร์และอัปโหลดไปยัง Container Registry

หลาม

  1. สร้างไดเร็กทอรีใหม่ชื่อ helloworld-python จากนั้นเปลี่ยนไดเร็กทอรีเป็น:

    mkdir helloworld-python
    cd helloworld-python
  2. สร้างไฟล์ใหม่ชื่อ app.py จากนั้นเพิ่มโค้ดต่อไปนี้:

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

    รหัสนี้สร้างเว็บเซิร์ฟเวอร์พื้นฐานที่รับฟังพอร์ตที่กำหนดโดยตัวแปรสภาพแวดล้อม PORT

แอปของคุณเสร็จสมบูรณ์และพร้อมที่จะบรรจุลงในคอนเทนเนอร์และอัปโหลดไปยัง Container Registry

ชวา

  1. ติดตั้ง Java SE 8 หรือใหม่กว่า JDK และ CURL

    โปรดทราบว่าเราจำเป็นต้องทำเช่นนี้เพื่อสร้างโครงการเว็บใหม่ในขั้นตอนถัดไป Dockerfile ซึ่งจะอธิบายในภายหลัง จะโหลดการอ้างอิงทั้งหมดลงในคอนเทนเนอร์

  2. จากคอนโซล ให้สร้างโปรเจ็กต์เว็บเปล่าใหม่โดยใช้ cURL จากนั้นแตกไฟล์คำสั่ง:

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

    สิ่งนี้จะสร้างโปรเจ็กต์ SpringBoot

  3. อัปเดตคลาส SpringBootApplication ใน src/main/java/com/example/helloworld/HelloworldApplication.java โดยเพิ่ม @RestController เพื่อจัดการ / mapping และเพิ่มฟิลด์ @Value เพื่อจัดเตรียมตัวแปรสภาพแวดล้อม 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);
      }
    }
    

    รหัสนี้สร้างเว็บเซิร์ฟเวอร์พื้นฐานที่รับฟังพอร์ตที่กำหนดโดยตัวแปรสภาพแวดล้อม PORT

แอปของคุณเสร็จสมบูรณ์และพร้อมที่จะบรรจุลงในคอนเทนเนอร์และอัปโหลดไปยัง Container Registry

ขั้นตอนที่ 2 : ทำคอนเทนเนอร์แอปและอัปโหลดไปยัง Container Registry

  1. จัดเก็บแอปตัวอย่างโดยการสร้างไฟล์ใหม่ชื่อ Dockerfile ในไดเร็กทอรีเดียวกันกับไฟล์ต้นฉบับ คัดลอกเนื้อหาต่อไปนี้ลงในไฟล์ของคุณ

    ไป

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

    โหนด 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" ]
    

    หลาม

    # 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
    

    ชวา

    # 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. สร้างอิมเมจคอนเทนเนอร์โดยใช้ Cloud Build โดยเรียกใช้คำสั่งต่อไปนี้จากไดเรกทอรีที่มี Dockerfile ของคุณ:

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

    เมื่อสำเร็จ คุณจะเห็นข้อความ SUCCESS ที่มีชื่อรูปภาพ
    ( gcr.io/ PROJECT_ID /helloworld )

ขณะนี้อิมเมจคอนเทนเนอร์ถูกจัดเก็บไว้ใน Container Registry และสามารถนำมาใช้ซ้ำได้หากต้องการ

โปรดทราบว่าแทนที่จะใช้ Cloud Build คุณสามารถใช้ Docker เวอร์ชันที่ติดตั้งในเครื่องเพื่อ สร้างคอนเทนเนอร์ในเครื่องได้

ขั้นตอนที่ 3 : ปรับใช้คอนเทนเนอร์อิมเมจกับ Cloud Run

  1. ปรับใช้โดยใช้คำสั่งต่อไปนี้:

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

  2. เมื่อได้รับแจ้ง:

เพื่อประสิทธิภาพที่ดีที่สุด ให้จัดตำแหน่งบริการ Cloud Run ของคุณกับโฮสติ้งโดยใช้ภูมิภาคต่อไปนี้:

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

รองรับการเขียนซ้ำไปยัง Cloud Run จาก Hosting ในภูมิภาคต่อไปนี้:

  • 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. รอสักครู่เพื่อให้การปรับใช้งานเสร็จสิ้น เมื่อสำเร็จ บรรทัดคำสั่งจะแสดง URL ของบริการ ตัวอย่างเช่น: https://helloworld- RANDOM_HASH -us-central1.a.run.app

  2. เยี่ยมชมคอนเทนเนอร์ที่ใช้งานของคุณโดยเปิด URL ของบริการในเว็บเบราว์เซอร์

ขั้นตอนต่อไปจะอธิบายวิธีเข้าถึงแอปที่มีคอนเทนเนอร์นี้ จาก URL โฮสติ้งของ Firebase เพื่อให้สามารถสร้างเนื้อหาแบบไดนามิกสำหรับไซต์ที่โฮสต์โดย Firebase ได้

ขั้นตอนที่ 4: คำขอโฮสต์โดยตรงไปยังแอปคอนเทนเนอร์ของคุณ

ด้วย กฎการเขียนซ้ำ คุณสามารถส่งคำขอที่ตรงกับรูปแบบเฉพาะไปยังปลายทางเดียวได้

ตัวอย่างต่อไปนี้แสดงวิธีส่งคำขอทั้งหมดจากเพจ /helloworld บนไซต์โฮสติ้งของคุณเพื่อทริกเกอร์การเริ่มต้นและการทำงานของอินสแตนซ์คอนเทนเนอร์ helloworld ของคุณ

  1. ทำให้เเน่นอน:

    สำหรับคำแนะนำโดยละเอียดเกี่ยวกับการติดตั้ง CLI และการเริ่มต้นโฮสติ้ง โปรดดู คู่มือเริ่มต้นใช้งานโฮสติ้ง

  2. เปิด ไฟล์ firebase.json ของคุณ

  3. เพิ่มการกำหนดค่า rewrite ต่อไปนี้ในส่วน 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. ปรับใช้การกำหนดค่าโฮสติ้งของคุณกับไซต์ของคุณโดยการรันคำสั่งต่อไปนี้จากรากของไดเร็กทอรีโปรเจ็กต์ของคุณ:

    firebase deploy --only hosting

ขณะนี้คุณสามารถเข้าถึงคอนเทนเนอร์ของคุณผ่านทาง URL ต่อไปนี้:

ไปที่หน้าการกำหนดค่าโฮสติ้งเพื่อดู รายละเอียดเพิ่มเติมเกี่ยวกับกฎการเขียนใหม่ คุณยังสามารถเรียนรู้เกี่ยวกับ ลำดับความสำคัญของการตอบกลับ สำหรับการกำหนดค่าโฮสติ้งต่างๆ

ทดสอบในพื้นที่

ในระหว่างการพัฒนา คุณสามารถเรียกใช้และทดสอบอิมเมจคอนเทนเนอร์ในเครื่องได้ สำหรับคำแนะนำโดยละเอียด โปรดไปที่ เอกสารประกอบของ Cloud Run

ขั้นตอนถัดไป