Catch up on highlights from Firebase at Google I/O 2023. Learn more

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

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

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

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


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

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

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

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

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

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

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

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

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

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

    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 เพื่อจัดการ / การแมปและเพิ่มฟิลด์ @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. เมื่อได้รับแจ้ง:

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

  4. เยี่ยมชมคอนเทนเนอร์ที่ใช้งานของคุณโดยเปิด 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

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