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

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

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

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

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


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

  1. اكتب تطبيق Hello World بسيطًا
  2. قم بوضع التطبيق في حاوية وتحميله إلى سجل الحاوية
  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 للتعامل مع / التعيين وأيضًا إضافة حقل @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 : قم بوضع التطبيق في حاوية وتحميله إلى سجل الحاوية

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

يتم الآن تخزين صورة الحاوية في سجل الحاوية ويمكن إعادة استخدامها إذا رغبت في ذلك.

لاحظ أنه بدلاً من 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 من الاستضافة في المناطق التالية:

  • 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 التالية:

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

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

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

اختبار محليا

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

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