Ofrezca contenido dinámico y aloje microservicios con Cloud Run

Combine Cloud Run con Firebase Hosting para generar y ofrecer su contenido dinámico o crear API REST como microservicios.

Con Cloud Run , puede implementar una aplicación empaquetada en una imagen de contenedor. Luego, usando Firebase Hosting, puedes dirigir solicitudes HTTPS para activar tu aplicación en contenedores.

  • Cloud Run admite varios lenguajes (incluidos Go, Node.js, Python y Java), lo que le brinda la flexibilidad de utilizar el lenguaje de programación y el marco de su elección.
  • Cloud Run escala automática y horizontalmente la imagen de su contenedor para manejar las solicitudes recibidas y luego lo reduce cuando la demanda disminuye.
  • Solo paga por la CPU, la memoria y las redes consumidas durante el manejo de solicitudes.

Para ver ejemplos de casos de uso y ejemplos de Cloud Run integrado con Firebase Hosting, visite nuestra descripción general sin servidor .


Esta guía le muestra cómo:

  1. Escribe una aplicación sencilla de Hola Mundo.
  2. Contenga una aplicación y cárguela en Container Registry
  3. Implementar la imagen del contenedor en Cloud Run
  4. Solicitudes de alojamiento directo a su aplicación en contenedores

Tenga en cuenta que para mejorar el rendimiento de la entrega de contenido dinámico, opcionalmente puede ajustar la configuración de la caché .

Antes de que empieces

Antes de usar Cloud Run, debes completar algunas tareas iniciales, incluida la configuración de una cuenta de facturación de Cloud, habilitar la API de Cloud Run e instalar la herramienta de línea de comandos gcloud .

Configura la facturación de tu proyecto

Cloud Run ofrece una cuota de uso gratuita , pero aun así debes tener una cuenta de facturación de Cloud asociada a tu proyecto de Firebase para usar o probar Cloud Run.

Habilite la API e instale el SDK

  1. Habilite la API de Cloud Run en la consola de API de Google:

    1. Abra la página API de Cloud Run en la consola de API de Google.

    2. Cuando se le solicite, seleccione su proyecto de Firebase.

    3. Haga clic en Habilitar en la página API de Cloud Run.

  2. Instale e inicialice el SDK de la nube.

  3. Comprueba que la herramienta gcloud esté configurada para el proyecto correcto:

    gcloud config list

Paso 1 : escriba la aplicación de muestra

Tenga en cuenta que Cloud Run admite muchos otros idiomas además de los idiomas que se muestran en el siguiente ejemplo.

Ir

  1. Cree un nuevo directorio llamado helloworld-go y luego cambie el directorio a él:

    mkdir helloworld-go
    cd helloworld-go
  2. Cree un nuevo archivo llamado helloworld.go y luego agregue el siguiente 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 crea un servidor web básico que escucha en el puerto definido por la variable de entorno PORT .

Su aplicación está terminada y lista para ser contenedorizada y cargada en Container Registry.

Nodo.js

  1. Cree un nuevo directorio llamado helloworld-nodejs y luego cambie el directorio a él:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Cree un archivo package.json con el siguiente contenido:

    {
      "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. Cree un nuevo archivo llamado index.js y luego agregue el siguiente 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 crea un servidor web básico que escucha en el puerto definido por la variable de entorno PORT .

Su aplicación está terminada y lista para ser contenedorizada y cargada en Container Registry.

Pitón

  1. Cree un nuevo directorio llamado helloworld-python , luego cambie el directorio a él:

    mkdir helloworld-python
    cd helloworld-python
  2. Cree un nuevo archivo llamado app.py y luego agregue el siguiente 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 crea un servidor web básico que escucha en el puerto definido por la variable de entorno PORT .

Su aplicación está terminada y lista para ser contenedorizada y cargada en Container Registry.

Java

  1. Instale Java SE 8 o posterior, JDK y CURL .

    Tenga en cuenta que solo necesitamos hacer esto para crear el nuevo proyecto web en el siguiente paso. El Dockerfile, que se describe más adelante, cargará todas las dependencias en el contenedor.

  2. Desde la consola, cree un nuevo proyecto web vacío usando cURL y luego descomprima los comandos:

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

    Esto crea un proyecto SpringBoot.

  3. Actualice la clase SpringBootApplication en src/main/java/com/example/helloworld/HelloworldApplication.java agregando un @RestController para manejar el mapeo / y también agregue un campo @Value para proporcionar la variable de entorno 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 crea un servidor web básico que escucha en el puerto definido por la variable de entorno PORT .

Su aplicación está terminada y lista para ser contenedorizada y cargada en Container Registry.

Paso 2 : Contenga una aplicación y cárguela en Container Registry

  1. Contenga la aplicación de muestra creando un nuevo archivo llamado Dockerfile en el mismo directorio que los archivos fuente. Copie el siguiente contenido en su archivo.

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

    Nodo.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ón

    # 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. Cree su imagen de contenedor usando Cloud Build ejecutando el siguiente comando desde el directorio que contiene su Dockerfile:

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

    Si tiene éxito, verá un mensaje de ÉXITO que contiene el nombre de la imagen.
    ( gcr.io/ PROJECT_ID /helloworld ).

La imagen del contenedor ahora está almacenada en Container Registry y puede reutilizarse si lo desea.

Tenga en cuenta que, en lugar de Cloud Build, puede utilizar una versión de Docker instalada localmente para crear su contenedor localmente .

Paso 3 : implementar la imagen del contenedor en Cloud Run

  1. Implemente usando el siguiente comando:

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

  2. Cuando se le solicite:

Para obtener el mejor rendimiento, coloque su servicio Cloud Run con Hosting usando las siguientes regiones:

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

Las reescrituras en Cloud Run desde Hosting se admiten en las siguientes regiones:

  • 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. Espere unos momentos hasta que se complete la implementación. En caso de éxito, la línea de comando muestra la URL del servicio. Por ejemplo https://helloworld- RANDOM_HASH -us-central1.a.run.app

  2. Visite su contenedor implementado abriendo la URL del servicio en un navegador web.

El siguiente paso le explica cómo acceder a esta aplicación en contenedores desde una URL de Firebase Hosting para que pueda generar contenido dinámico para su sitio alojado en Firebase.

Paso 4: Solicitudes de alojamiento directo a su aplicación en contenedores

Con reglas de reescritura , puede dirigir solicitudes que coincidan con patrones específicos a un único destino.

El siguiente ejemplo muestra cómo dirigir todas las solicitudes desde la página /helloworld en su sitio de Hosting para activar el inicio y la ejecución de su instancia de contenedor helloworld .

  1. Asegúrate de eso:

    Para obtener instrucciones detalladas sobre cómo instalar la CLI e inicializar Hosting, consulte la guía de introducción a Hosting .

  2. Abra su archivo firebase.json .

  3. Agregue la siguiente configuración rewrite en la sección 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. Implemente su configuración de alojamiento en su sitio ejecutando el siguiente comando desde la raíz del directorio de su proyecto:

    firebase deploy --only hosting

Ahora se puede acceder a su contenedor a través de las siguientes URL:

  • Tus subdominios de Firebase:
    PROJECT_ID .web.app/ y PROJECT_ID .firebaseapp.com/

  • Cualquier dominio personalizado conectado:
    CUSTOM_DOMAIN /

Visite la página de configuración de Hosting para obtener más detalles sobre las reglas de reescritura . También puede obtener información sobre el orden de prioridad de las respuestas para varias configuraciones de Hosting.

Prueba localmente

Durante el desarrollo, puede ejecutar y probar la imagen de su contenedor localmente. Para obtener instrucciones detalladas, visite la documentación de Cloud Run .

Próximos pasos