Ofereça conteúdo dinâmico e hospede microsserviços com o Cloud Run

Combine o Cloud Run com o Firebase Hosting para gerar e veicular seu conteúdo dinâmico ou criar APIs REST como microsserviços.

Usando o Cloud Run , você pode implantar um aplicativo empacotado em uma imagem de contêiner. Em seguida, usando o Firebase Hosting, você pode direcionar solicitações HTTPS para acionar seu aplicativo em contêiner.

  • O Cloud Run oferece suporte a diversas linguagens (incluindo Go, Node.js, Python e Java), proporcionando flexibilidade para usar a linguagem de programação e a estrutura de sua preferência.
  • O Cloud Run dimensiona automaticamente e horizontalmente a imagem do contêiner para lidar com as solicitações recebidas e depois reduz quando a demanda diminui.
  • Você paga apenas pela CPU, memória e rede consumidas durante o tratamento da solicitação.

Para ver exemplos de casos de uso e exemplos do Cloud Run integrado ao Firebase Hosting, visite nossa visão geral sem servidor .


Este guia mostra como:

  1. Escreva um aplicativo simples Hello World
  2. Conteinerize um aplicativo e carregue-o no Container Registry
  3. Implantar a imagem do contêiner no Cloud Run
  4. Solicitações diretas de hospedagem para seu aplicativo em contêiner

Observe que, para melhorar o desempenho do fornecimento de conteúdo dinâmico, você pode opcionalmente ajustar as configurações de cache .

Antes de você começar

Antes de usar o Cloud Run, você precisa concluir algumas tarefas iniciais, incluindo a configuração de uma conta do Cloud Billing, a ativação da API Cloud Run e a instalação da ferramenta de linha de comando gcloud .

Configure o faturamento para seu projeto

O Cloud Run oferece cota de uso gratuita , mas você ainda precisa ter uma conta do Cloud Billing associada ao seu projeto do Firebase para usar ou testar o Cloud Run.

Habilite a API e instale o SDK

  1. Ative a API Cloud Run no console de APIs do Google:

    1. Abra a página da API Cloud Run no console de APIs do Google.

    2. Quando solicitado, selecione seu projeto do Firebase.

    3. Clique em Ativar na página da API Cloud Run.

  2. Instale e inicialize o Cloud SDK.

  3. Verifique se a ferramenta gcloud está configurada para o projeto correto:

    gcloud config list

Etapa 1 : Escreva o aplicativo de exemplo

Observe que o Cloud Run oferece suporte a muitas outras linguagens além das mostradas no exemplo a seguir.

Ir

  1. Crie um novo diretório chamado helloworld-go e altere o diretório para ele:

    mkdir helloworld-go
    cd helloworld-go
  2. Crie um novo arquivo chamado helloworld.go e adicione o seguinte código:

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

    Este código cria um servidor web básico que escuta na porta definida pela variável de ambiente PORT .

Seu aplicativo está concluído e pronto para ser conteinerizado e carregado no Container Registry.

Node.js

  1. Crie um novo diretório chamado helloworld-nodejs e altere o diretório para ele:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Crie um arquivo package.json com o seguinte conteúdo:

    {
      "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. Crie um novo arquivo chamado index.js e adicione o seguinte código:

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

    Este código cria um servidor web básico que escuta na porta definida pela variável de ambiente PORT .

Seu aplicativo está concluído e pronto para ser conteinerizado e carregado no Container Registry.

Pitão

  1. Crie um novo diretório chamado helloworld-python e altere o diretório para ele:

    mkdir helloworld-python
    cd helloworld-python
  2. Crie um novo arquivo chamado app.py e adicione o seguinte código:

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

    Este código cria um servidor web básico que escuta na porta definida pela variável de ambiente PORT .

Seu aplicativo está concluído e pronto para ser conteinerizado e carregado no Container Registry.

Java

  1. Instale Java SE 8 ou posterior JDK e CURL .

    Observe que só precisamos fazer isso para criar o novo projeto web na próxima etapa. O Dockerfile, descrito posteriormente, carregará todas as dependências no contêiner.

  2. No console, crie um novo projeto web vazio usando cURL e descompacte os comandos:

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

    Isso cria um projeto SpringBoot.

  3. Atualize a classe SpringBootApplication em src/main/java/com/example/helloworld/HelloworldApplication.java adicionando um @RestController para lidar com o mapeamento / e também adicione um campo @Value para fornecer a variável de ambiente 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);
      }
    }
    

    Este código cria um servidor web básico que escuta na porta definida pela variável de ambiente PORT .

Seu aplicativo está concluído e pronto para ser conteinerizado e carregado no Container Registry.

Etapa 2 : conteinerizar um aplicativo e carregá-lo no Container Registry

  1. Conteinerize o aplicativo de exemplo criando um novo arquivo chamado Dockerfile no mesmo diretório dos arquivos de origem. Copie o seguinte conteúdo em seu arquivo.

    Ir

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

    Pitão

    # 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
    

    Java

    # 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. Crie sua imagem de contêiner usando o Cloud Build executando o seguinte comando no diretório que contém seu Dockerfile:

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

    Após sucesso, você verá uma mensagem de SUCESSO contendo o nome da imagem
    ( gcr.io/ PROJECT_ID /helloworld ).

A imagem do contêiner agora está armazenada no Container Registry e pode ser reutilizada, se desejado.

Observe que, em vez do Cloud Build, você pode usar uma versão do Docker instalada localmente para criar seu contêiner localmente .

Etapa 3 : implantar a imagem do contêiner no Cloud Run

  1. Implante usando o seguinte comando:

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

  2. Quando solicitado:

Para obter o melhor desempenho, coloque seu serviço Cloud Run com hospedagem usando as seguintes regiões:

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

As reescritas no Cloud Run a partir do Hosting são compatíveis com as seguintes regiões:

  • 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. Aguarde alguns instantes até que a implantação seja concluída. Em caso de sucesso, a linha de comando exibe a URL do serviço. Por exemplo https://helloworld- RANDOM_HASH -us-central1.a.run.app

  2. Visite seu contêiner implantado abrindo a URL do serviço em um navegador da web.

A próxima etapa mostra como acessar esse aplicativo em contêiner a partir de um URL do Firebase Hosting para que ele possa gerar conteúdo dinâmico para seu site hospedado no Firebase.

Etapa 4: solicitações de hospedagem direta para seu aplicativo em contêiner

Com regras de reescrita , você pode direcionar solicitações que correspondam a padrões específicos para um único destino.

O exemplo a seguir mostra como direcionar todas as solicitações da página /helloworld em seu site de hospedagem para acionar a inicialização e a execução de sua instância de contêiner helloworld .

  1. Certifique-se de que:

    Para obter instruções detalhadas sobre como instalar a CLI e inicializar o Hosting, consulte o guia de primeiros passos do Hosting .

  2. Abra seu arquivo firebase.json .

  3. Adicione a seguinte configuração rewrite na seção 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. Implante sua configuração de hospedagem em seu site executando o seguinte comando na raiz do diretório do seu projeto:

    firebase deploy --only hosting

Seu contêiner agora pode ser acessado por meio dos seguintes URLs:

  • Seus subdomínios do Firebase:
    PROJECT_ID .web.app/ e PROJECT_ID .firebaseapp.com/

  • Quaisquer domínios personalizados conectados:
    CUSTOM_DOMAIN /

Visite a página de configuração de hospedagem para obter mais detalhes sobre regras de reescrita . Você também pode aprender sobre a ordem de prioridade das respostas para diversas configurações de hospedagem.

Teste localmente

Durante o desenvolvimento, você pode executar e testar a imagem do contêiner localmente. Para obter instruções detalhadas, visite a documentação do Cloud Run .

Próximos passos