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

خدمة المحتوى الديناميكي واستضافة الخدمات المصغرة باستخدام Cloud Run

قم بإقران Cloud Run مع Firebase Hosting لإنشاء المحتوى الديناميكي الخاص بك وتقديمه أو إنشاء واجهات برمجة تطبيقات REST كخدمات صغيرة.

باستخدام Cloud Run ، يمكنك نشر تطبيق تم تجميعه في صورة حاوية. بعد ذلك ، باستخدام Firebase Hosting ، يمكنك توجيه طلبات HTTPS لتشغيل تطبيقك المعبأ في حاويات.

  • يدعم Cloud Run العديد من اللغات (بما في ذلك Go و Node.js و Python و Java) ، مما يمنحك المرونة في استخدام لغة البرمجة وإطار العمل الذي تختاره.
  • يقوم Cloud Run تلقائيًا وأفقياً بتحجيم صورة الحاوية الخاصة بك للتعامل مع الطلبات المستلمة ، ثم يتقلص عندما ينخفض ​​الطلب.
  • أنت تدفع فقط مقابل وحدة المعالجة المركزية والذاكرة والشبكات المستهلكة أثناء معالجة الطلب.

على سبيل المثال ، حالات الاستخدام والعينات لـ Cloud Run المدمجة مع Firebase Hosting ، تفضل بزيارة نظرة عامة على الخادم بدون خادم .


يوضح لك هذا الدليل كيفية:

  1. اكتب تطبيق Hello World بسيطًا
  2. قم بتضمين تطبيق وتحميله إلى Container Registry
  3. انشر صورة الحاوية في Cloud Run
  4. طلبات الاستضافة المباشرة لتطبيقك المعبأ في حاويات

لاحظ أنه لتحسين أداء عرض المحتوى الديناميكي ، يمكنك ضبط إعدادات ذاكرة التخزين المؤقت اختياريًا.

قبل ان تبدأ

قبل استخدام Cloud Run ، تحتاج إلى إكمال بعض المهام الأولية ، بما في ذلك إعداد حساب Cloud Billing ، وتمكين Cloud Run API ، وتثبيت أداة سطر أوامر gcloud .

قم بإعداد الفواتير لمشروعك

يوفر Cloud Run حصة استخدام مجانية ، ولكن لا يزال يتعين عليك امتلاك حساب Cloud Billing مرتبط بمشروع 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.

Node.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"]
    

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

    بايثون

    # 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

    عند النجاح ، سترى رسالة نجاح تحتوي على اسم الصورة
    ( 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 التالية:

  • نطاقات Firebase الفرعية الخاصة بك:
    PROJECT_ID .web.app/ و PROJECT_ID .firebaseapp.com/

  • أي مجالات مخصصة متصلة:
    CUSTOM_DOMAIN /

قم بزيارة صفحة تهيئة الاستضافة للحصول على مزيد من التفاصيل حول قواعد إعادة الكتابة . يمكنك أيضًا التعرف على ترتيب أولويات الاستجابات لتكوينات الاستضافة المختلفة.

اختبر محليًا

أثناء التطوير ، يمكنك تشغيل صورة الحاوية الخاصة بك واختبارها محليًا. للحصول على إرشادات مفصلة ، قم بزيارة وثائق Cloud Run .

الخطوات التالية