Ir a la consola

Entrega contenido dinámico y aloja microservicios con Cloud Run

Usa Cloud Run con Firebase Hosting para generar y entregar tu contenido dinámico o compilar las API de REST como microservicios.

Cloud Run te permite implementar aplicaciones empaquetadas en imágenes de contenedor. Luego, puedes usar Firebase Hosting a fin de dirigir las solicitudes HTTPS para activar una app en contenedor.

  • Cloud Run admite varios lenguajes (como Go, Node.js, Python y Java), por lo que puedes usar el marco de trabajo y lenguaje de programación que prefieras.
  • Cloud Run escala la imagen de contenedor de manera automática y horizontal para controlar las solicitudes que se reciben y, luego, disminuye la escala cuando disminuye la demanda.
  • Solo debes pagar por la CPU, la memoria y las herramientas de redes que se utilicen durante la administración de la solicitud.

Consulta la descripción general de la computación sin servidores para ver muestras y casos prácticos de ejemplo de Cloud Run integrado en Firebase Hosting.


En esta guía, se indica cómo realizar las siguientes acciones:

  1. Escribir una app de Hello World sencilla
  2. Organizar una app en contenedores y subirla a Container Registry
  3. Implementar la imagen del contenedor en Cloud Run
  4. Dirigir las solicitudes de Hosting a tu app en contenedor

Recuerda que si quieres mejorar el rendimiento de la entrega de contenido dinámico, puedes configurar la caché.

Antes de comenzar

Antes de usar Cloud Run, debes completar algunas tareas iniciales, como configurar una cuenta de facturación, habilitar la API de Cloud Run y, también, instalar la herramienta de línea de comandos de gcloud.

Configura la facturación para el proyecto

Cloud Run ofrece una cuota de uso gratuito. Sin embargo, debes tener una cuenta de facturación asociada con tu proyecto de Firebase para usar o probar Cloud Run.

Habilita la API e instala el SDK

  1. Habilita la API de Cloud Run en la consola de las API de Google:

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

    2. Cuando se te pida, selecciona tu proyecto de Firebase.

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

  2. Instala e inicializa el SDK de Cloud.

Instala el componente Beta de gcloud

  1. Ejecuta el siguiente comando para instalar el componente Beta de gcloud:

    gcloud components install beta
  2. Actualiza los componentes, como se indica a continuación:

    gcloud components update
  3. Asegúrate de que la herramienta gcloud esté configurada para el proyecto adecuado:

    gcloud config list

Paso 1: Escribe la aplicación de muestra

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

Go

  1. Crea un directorio nuevo llamado helloworld-go y, luego, usa el comando de cambio de directorio de la siguiente manera:

    mkdir helloworld-go
    cd helloworld-go
  2. Crea un archivo nuevo llamado helloworld.go y, a continuación, agrega el siguiente código:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	log.Print("Hello world received a request.")
    	target := os.Getenv("TARGET")
    	if target == "" {
    		target = "World"
    	}
    	fmt.Fprintf(w, "Hello %s!\n", target)
    }
    
    func main() {
    	log.Print("Hello world sample started.")
    
    	http.HandleFunc("/", handler)
    
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    

    Con este código, se crea un servidor web básico que recibe datos en el puerto definido por la variable de entorno PORT.

La app está lista para organizarla en contenedores y subirla a Container Registry.

Node.js

  1. Crea un directorio nuevo llamado helloworld-nodejs y, luego, usa el comando de cambio de directorio de la siguiente manera:

    mkdir helloworld-nodejs
    cd helloworld-nodejs
  2. Crea el 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.16.4"
      }
    }
    
  3. Crea un archivo nuevo llamado index.js y, a continuación, agrega 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}!`);
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });
    

    Con este código, se crea un servidor web básico que recibe datos en el puerto definido por la variable de entorno PORT.

La app está lista para organizarla en contenedores y subirla a Container Registry.

Python

  1. Crea un directorio nuevo llamado helloworld-python y, luego, usa el comando de cambio de directorio de la siguiente manera:

    mkdir helloworld-python
    cd helloworld-python
  2. Crea un archivo nuevo llamado app.py y, a continuación, agrega 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)))
    

    Con este código, se crea un servidor web básico que recibe datos en el puerto definido por la variable de entorno PORT.

La app está lista para organizarla en contenedores y subirla a Container Registry.

Java

  1. Instala Java SE 8 o un JDK más reciente y CURL.

    Ten en cuenta que solo debemos realizar lo anterior para crear el proyecto web nuevo en el próximo paso. El Dockerfile, que se describe más adelante, cargará todas las dependencias en el contenedor.

  2. En la consola, usa curl para crear un proyecto web nuevo y vacío y, luego, descomprime los comandos:

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

    Se creará un proyecto de SpringBoot.

  3. Agrega un @RestController para controlar el mapeo de / a fin de actualizar la clase SpringBootApplication en src/main/java/com/example/helloworld/HelloworldApplication.java. Agrega también 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 message;
    
    	@RestController
    	class HelloworldController {
    		@GetMapping("/")
    		String hello() {
    			return "Hello " + message + "!";
    		}
    	}
    
    	public static void main(String[] args) {
    		SpringApplication.run(HelloworldApplication.class, args);
    	}
    }
    

    Con este código, se crea un servidor web básico que recibe datos en el puerto definido por la variable de entorno PORT.

La app está lista para organizarla en contenedores y subirla a Container Registry.

Paso 2: Distribuye una app en contenedores y súbela a Container Registry

  1. Crea un archivo nuevo llamado Dockerfile en el mismo directorio que los archivos de origen para organizar la app de muestra en contenedores. Copia el siguiente contenido en el archivo.

    Go

    # Use the offical Golang image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang as builder
    
    # Copy local code to the container image.
    WORKDIR /go/src/github.com/knative/docs/helloworld
    COPY . .
    
    # Build the outyet command inside the container.
    # (You may fetch or manage dependencies here,
    # either manually or with a tool like "godep".)
    RUN CGO_ENABLED=0 GOOS=linux go build -v -o helloworld
    
    # Use a Docker multi-stage build to create a lean production image.
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM alpine
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /go/src/github.com/knative/docs/helloworld/helloworld /helloworld
    
    # Service must listen to $PORT environment variable.
    # This default value facilitates local development.
    ENV PORT 8080
    
    # Run the web service on container startup.
    CMD ["/helloworld"]
    

    Node.js

    # Use the official Node.js 10 image.
    # https://hub.docker.com/_/node
    FROM node:10
    
    # 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 . .
    
    # Service must listen to $PORT environment variable.
    # This default value facilitates local development.
    ENV PORT 8080
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    Python

    # Use the official Python image.
    # https://hub.docker.com/_/python
    FROM python
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . .
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Service must listen to $PORT environment variable.
    # This default value facilitates local development.
    ENV PORT 8080
    
    # 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 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
    
    # Service must listen to $PORT environment variable.
    # This default value facilitates local development.
    ENV PORT 8080
    
    # Run the web service on container startup.
    CMD ["java","-Djava.security.egd=file:/dev/./urandom","-Dserver.port=${PORT}","-jar","/helloworld.jar"]
    

  2. Usa Cloud Build a fin de compilar la imagen de contenedor. Para ello, ejecuta el siguiente comando desde el directorio que contiene el Dockerfile:

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

    Tras la ejecución satisfactoria del comando, verás el mensaje SUCCESS con el nombre de la imagen
    (gcr.io/projectID/helloworld).

La imagen del contenedor ahora se almacena en Container Registry y la puedes volver a usar si lo deseas.

Ten en cuenta que, en lugar de Cloud Build, puedes usar una versión de Docker instalada de manera local, para compilar el contenedor a nivel local.

Paso 3: Implementa la imagen de contenedor en Cloud Run

  1. Realiza la implementación con el siguiente comando:

    gcloud beta run deploy --image gcr.io/projectID/helloworld

  2. Realiza las siguientes acciones cuando se te solicite:

  3. Espera unos instantes a que finalice la implementación. Si la operación es exitosa, la línea de comandos mostrará la URL de servicio. Por ejemplo:

    https://helloworld-random_hash-us-central1.a.run.app
  4. Abre la URL de servicio en un navegador web para visitar el contenedor implementado.

En el siguiente paso, se explica cómo acceder a la app en contenedores desde una URL de Firebase Hosting a fin de que esta pueda generar contenido dinámico para el sitio alojado en Firebase.

Paso 4: Dirige las solicitudes de Hosting hacia la app distribuida en contenedores

Con las reglas de reescritura, puedes dirigir solicitudes que coincidan con patrones específicos a un mismo destino.

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

  1. Asegúrate de cumplir con estas condiciones:

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

  2. Abre el archivo firebase.json.

  3. Agrega la siguiente configuración de rewrite en la sección hosting:

    "hosting": {
      // ...
    
      // Add the "rewrites" attribute within "hosting"
      "rewrites": [ {
        "source": "**",
        "run": {
          "serviceId": "helloworld",  // "service name" (from when you deployed the container image)
          "region": "us-central1"     // optional (if omitted, default is us-central1)
        }
      } ]
    }
    
  4. Implementa la configuración de Hosting en tu sitio. Para ello, ejecuta el siguiente comando desde la raíz del directorio del proyecto:

    firebase deploy

Ahora se puede acceder al contenedor mediante las siguientes URL:

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

  • Cualquier dominio personalizado conectado: custom-domain/helloworld

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

Realiza pruebas locales

Durante el desarrollo, puedes ejecutar y probar la imagen del contenedor de manera local. Consulta la documentación de Cloud Run para obtener instrucciones detalladas.

Próximos pasos