使用 Cloud Run 提供動態內容和託管微服務

將 Cloud Run 與 Firebase 託管配對以生成和提供您的動態內容或將 REST API 構建為微服務。

使用雲中運行,可以部署在包裝容器的圖像的應用程序。然後,使用 Firebase 託管,您可以將 HTTPS 請求定向到觸發您的容器化應用程序。

  • 雲上運行支持多種語言(包括圍棋,Node.js的,Python和和Java),讓您使用您所選擇的編程語言和框架的靈活性。
  • 雲中運行自動水平縮放你的容器圖像處理接收到的請求,然後按比例縮小時的需求減少。
  • 你只了CPU,內存和請求處理過程中消耗的聯網。

對於火力地堡主機集成例如使用案例和樣本雲上運行,請訪問我們的無服務器的概述


本指南向您展示如何:

  1. 編寫一個簡單的 Hello World 應用程序
  2. 容器化應用程序並將其上傳到 Container Registry
  3. 將容器映像部署到 Cloud Run
  4. 將託管請求直接發送到您的容器化應用程序

請注意,以提高動態內容服務,您可以根據需要調整你的性能緩存設置

在你開始之前

使用雲中運行之前,您需要完成一些初始任務,包括建立雲結算帳戶,使雲中運行的API,並安裝gcloud命令行工具。

為您的項目設置結算

雲中運行提供免費使用配額,但你還是必須有一個雲結算帳戶與火力地堡項目相關聯的使用或嘗試雲中運行。

啟用API並安裝SDK

  1. 在 Google API 控制台中啟用 Cloud Run API:

    1. 打開雲中運行的API頁面在谷歌API控制台。

    2. 出現提示時,選擇您的 Firebase 項目。

    3. 點擊雲中運行API網頁上啟用

  2. 安裝和初始化雲SDK。

  3. 檢查gcloud工具被配置為正確的項目:

    gcloud config list

步驟1:編寫示例應用程序

需要注意的是雲中運行的支持許多其他語言,除了下面的示例中顯示的語言。

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

    此代碼創建的端口上偵聽由定義的一個基本的Web服務器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.16.4"
      }
    }
    
  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);
    });
    

    此代碼創建的端口上偵聽由定義的一個基本的Web服務器PORT的環境變量。

您的應用已完成並準備好進行容器化並上傳到 Container Registry。

Python

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

    此代碼創建的端口上偵聽由定義的一個基本的Web服務器PORT的環境變量。

您的應用已完成並準備好進行容器化並上傳到 Container Registry。

爪哇

  1. 安裝的Java SE 8或更高版本的JDK捲曲

    請注意,我們只需執行此操作即可在下一步中創建新的 Web 項目。 Dockerfile(稍後介紹)會將所有依賴項加載到容器中。

  2. 在控制台中,使用 cURL 創建一個新的空 Web 項目,然後解壓縮命令:

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

    這將創建一個 SpringBoot 項目。

  3. 更新SpringBootApplicationsrc/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);
      }
    }
    

    此代碼創建的端口上偵聽由定義的一個基本的Web服務器PORT的環境變量。

您的應用已完成並準備好進行容器化並上傳到 Container Registry。

第2步:Containerize一個應用程序,並把它上傳到容器註冊

  1. 通過創建的文件名為Containerize示例應用程序Dockerfile在同一個目錄中的源文件。將以下內容複製到您的文件中。

    # Use the official Golang image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    FROM golang:1.13 as builder
    
    # 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=linux 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" ]
    

    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
    

    爪哇

    # 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. 通過從包含 Dockerfile 的目錄運行以下命令,使用 Cloud Build 構建容器映像:

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

    成功後,您將看到一條包含圖像名稱的 SUCCESS 消息
    gcr.io/ PROJECT_ID /helloworld )。

容器映像現在存儲在 Container Registry 中,可以根據需要重新使用。

需要注意的是,不是雲構建,可以使用泊塢窗的本地安裝的版本在本地建立你的容器

步驟3:部署容器圖像雲運行

  1. 使用以下命令進行部署:

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

  2. 提示時:

  3. 稍等片刻,部署完成。成功後,命令行將顯示服務 URL。例如: https://helloworld- RANDOM_HASH -us-central1.a.run.app

  4. 通過在 Web 瀏覽器中打開服務 URL 來訪問您部署的容器。

下一步將引導您如何從火力地堡主機URL訪問此集裝箱的應用程序,以便它可以為您的火力地堡主辦的網站動態內容。

第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)
        }
      } ]
    }
    
  4. 通過從項目目錄的根目錄運行以下命令,將您的託管配置部署到您的站點:

    firebase deploy

現在可以通過以下 URL 訪問您的容器:

  • 您的 Firebase 子域:
    PROJECT_ID .web.app/PROJECT_ID .firebaseapp.com/

  • 任何連接的自定義域
    CUSTOM_DOMAIN /

訪問主機配置頁有關重寫規則的詳細信息。您還可以了解的響應優先順序為各種虛擬主機配置。

本地測試

在開發過程中,您可以在本地運行和測試您的容器映像。有關詳細說明,請訪問雲中運行的文檔

下一步