Démarrage rapide : Construire et déployer

Cette page explique comment créer une application Hello World simple, l'intégrer dans une image de conteneur, importer l'image de conteneur dans Container Registry, puis déployer l'image de conteneur dans Cloud Run. L'exemple est proposé dans plusieurs langages, mais notez que vous pouvez en utiliser d'autres en plus de ceux présentés.

Vous pouvez également suivre ce guide de démarrage rapide avec un compte de démonstration sur Qwiklabs.

Avant de commencer

  1. Connectez-vous à votre compte Google.

    Si vous n'en possédez pas déjà un, vous devez en créer un.

  2. Dans Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Cloud.

    Accéder à la page de sélection du projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud. Découvrez comment vérifier que la facturation est activée pour votre projet.

  4. Activez les Cloud Build and Cloud Run API.

    Activer les API

  5. Installez et initialisez le SDK Cloud.
  6. Mettez à jour les composants :
    gcloud components update

Écrire l'exemple d'application

Pour obtenir des instructions sur la création d’un exemple d’application Hello World exécutée dans Cloud Run, cliquez sur l’onglet correspondant à votre langage :

Go

  1. Créez un répertoire nommé helloworld-go et modifiez les sous-répertoires comme suit :

    mkdir helloworld-go
        cd helloworld-go
        
  2. Initialisez un fichier go.mod pour déclarer le module go :

    go mod init helloworld-go
        
  3. Créez un fichier nommé helloworld.go et collez-y le code suivant :

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

    Ce code crée un serveur Web de base, qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Node.js

  1. Créez un répertoire nommé helloworld-nodejs et modifiez les sous-répertoires comme suit :

    mkdir helloworld-nodejs
        cd helloworld-nodejs
        
  2. Créez un fichier package.json avec le contenu suivant :

    {
          "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. Dans le même répertoire, créez un fichier index.js, puis copiez-y les lignes suivantes :

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

    Ce code crée un serveur Web de base, qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Python

  1. Créez un répertoire nommé helloworld-python et modifiez les sous-répertoires comme suit :

    mkdir helloworld-python
        cd helloworld-python
        
  2. Créez un fichier nommé app.py et collez-y le code suivant :

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

    Ce code répond aux demandes avec notre message d'accueil "Hello World!". La gestion HTTP est effectuée par un serveur Web Gunicorn dans le conteneur. Lorsqu'il est appelé directement en local, ce code crée un serveur Web de base, qui écoute sur le port défini par la variable d'environnement PORT.

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Java

Créez une application Spring Boot.

  1. À partir de la console, créez un projet Web vide à l'aide des commandes CURL et unzip :

    curl https://start.spring.io/starter.zip \
            -d dependencies=web \
            -d javaVersion=1.8 \
            -d bootVersion=2.1.3.RELEASE \
            -d name=helloworld \
            -d artifactId=helloworld \
            -d baseDir=helloworld \
            -o helloworld.zip
        unzip helloworld.zip
        cd helloworld
        

    Un projet Spring Boot est créé.

  2. Mettez à jour la classe HelloworldApplication dans src/main/java/com/example/helloworld/HelloworldApplication.java en ajoutant une valeur @RestController pour gérer le mappage / et ajoutez également un champ @Value pour fournir la variable d'environnement 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);
        	}
        }
        

    Ce code crée un serveur Web de base, qui écoute le port défini par la variable d’environnement PORT.

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Pour déployer Java dans Cloud Run avec d'autres frameworks, consultez les exemples Knative pour Spark et Vert.x.

C#

  1. Installez le SDK .NET Core 3.1. Notez que nous n'avons à le faire que pour créer le projet Web à l'étape suivante. Le fichier Docker, décrit ultérieurement, chargera toutes les dépendances dans le conteneur.

  2. À partir de la console, créez un projet Web vide à l'aide de la commande dotnet :

    dotnet new web -o helloworld-csharp
        
  3. Remplacez le répertoire par helloworld-csharp.

  4. Mettez à jour la définition CreateHostBuilder dans Program.cs pour écouter sur le port défini par la variable d'environnement PORT :

    using System;
        using Microsoft.AspNetCore.Hosting;
        using Microsoft.Extensions.Hosting;
    
        namespace helloworld_csharp
        {
            public class Program
            {
                public static void Main(string[] args)
                {
                    CreateHostBuilder(args).Build().Run();
                }
    
                public static IHostBuilder CreateHostBuilder(string[] args)
                {
                    string port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
                    string url = String.Concat("http://0.0.0.0:", port);
    
                    return Host.CreateDefaultBuilder(args)
                        .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseStartup<Startup>().UseUrls(url);
                        });
                }
            }
        }

    Ce code crée un serveur Web de base, qui écoute le port défini par la variable d’environnement PORT.

  5. Créez un fichier nommé Startup.cs et collez-y le code suivant :

    using System;
        using Microsoft.AspNetCore.Builder;
        using Microsoft.AspNetCore.Hosting;
        using Microsoft.AspNetCore.Http;
        using Microsoft.Extensions.DependencyInjection;
        using Microsoft.Extensions.Hosting;
    
        namespace helloworld_csharp
        {
            public class Startup
            {
                // This method gets called by the runtime. Use this method to add services to the container.
                // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
                public void ConfigureServices(IServiceCollection services)
                {
                }
    
                // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
                public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
                {
                    if (env.IsDevelopment())
                    {
                        app.UseDeveloperExceptionPage();
                    }
    
                    app.UseRouting();
    
                    app.UseEndpoints(endpoints =>
                    {
                        endpoints.MapGet("/", async context =>
                        {
                            var target = Environment.GetEnvironmentVariable("TARGET") ?? "World";
                            await context.Response.WriteAsync($"Hello {target}!\n");
                        });
                    });
                }
            }
        }

    Ce code répond aux demandes avec notre message d'accueil "Hello World!".

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

PHP

  1. Créez un répertoire nommé helloworld-php et modifiez les sous-répertoires comme suit :

    mkdir helloworld-php
        cd helloworld-php
        
  2. Créez un fichier nommé index.php et collez-y le code suivant :

    <?php
        $target = getenv('TARGET', true) ?: 'World';
        echo sprintf("Hello %s!", $target);
        

    Ce code répond aux demandes avec notre message d'accueil "Hello World!". La gestion HTTP est effectuée par un serveur Web Apache dans le conteneur.

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Ruby

  1. Créez un répertoire nommé helloworld-ruby et modifiez les sous-répertoires comme suit :

    mkdir helloworld-ruby
        cd helloworld-ruby
        
  2. Créez un fichier nommé app.rb et collez-y le code suivant :

    require 'sinatra'
    
        set :bind, '0.0.0.0'
    
        get '/' do
          target = ENV['TARGET'] || 'World'
          "Hello #{target}!\n"
        end
        

    Ce code crée un serveur Web de base, qui écoute le port défini par la variable d’environnement PORT.

  3. Créez un nom de fichier Gemfile et copiez-y les éléments suivants :

    source 'https://rubygems.org'
    
        gem 'sinatra'
        gem 'rack', '>= 2.0.6'
        
  4. Si vous n'avez pas installé Bundler 2.0 ou une version ultérieure, installez Bundler.

  5. Générez un fichier Gemfile.lock en exécutant :

    bundle install

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Shell

  1. Créez un répertoire nommé helloworld-shell et modifiez les sous-répertoires comme suit :

    mkdir helloworld-shell
        cd helloworld-shell
        
  2. Créez un fichier script.sh avec le contenu suivant :

    #!/bin/sh
        echo Hello ${TARGET:=World}!
    
        

    Afin d'exécuter ce script shell à chaque requête entrante, cet exemple utilise un petit programme Go qui démarre un serveur Web de base et écoute le port défini par la variable d'environnement PORT.

  3. Créez un fichier invoke.go avec le contenu suivant :

    package main
    
        import (
        	"fmt"
        	"log"
        	"net/http"
        	"os"
        	"os/exec"
        )
    
        func handler(w http.ResponseWriter, r *http.Request) {
        	cmd := exec.CommandContext(r.Context(), "/bin/sh", "script.sh")
        	cmd.Stderr = os.Stderr
        	out, err := cmd.Output()
        	if err != nil {
        		w.WriteHeader(500)
        	}
        	w.Write(out)
        }
    
        func main() {
        	http.HandleFunc("/", handler)
    
        	port := os.Getenv("PORT")
        	if port == "" {
        		port = "8080"
        	}
    
        	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
        }
        

Votre application est terminée et prête à être conteneurisée, puis importée dans Container Registry.

Autre

Cloud Run est compatible avec la plupart des langages. Pour obtenir des exemples simples dans d'autres langages que ceux présentés dans ce tableau, consultez les pages :

Cependant, dans tous ces exemples, ne tenez pas compte des informations sur service.yaml et Docker Hub, car Cloud Run ne les utilise pas.

Conteneuriser une application et l'importer dans Container Registry

Pour conteneuriser l'exemple d'application, créez un fichier nommé Dockerfile dans le même répertoire que les fichiers sources, puis copiez le contenu suivant :

Go

# Use the official 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:1.13 as builder

    # Create and change to the app directory.
    WORKDIR /app

    # Retrieve application dependencies.
    # This allows the container build to reuse cached dependencies.
    COPY go.* ./
    RUN go mod download

    # Copy local code to the container image.
    COPY . ./

    # Build the binary.
    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"]
    

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

Ajoutez un fichier .dockerignore pour exclure des fichiers de votre image de conteneur. Pour empêcher l'importation de fichiers dans Cloud Build, ajoutez un fichier .gcloudignore supplémentaire.

Dockerfile
    README.md
    node_modules
    npm-debug.log
    

Python

Le fichier Python Dockerfile démarre un serveur Web Firicorn, qui écoute le port défini par la variable d'environnement PORT :

# Use the official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.7-slim

    # 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 app:app
    

Ajoutez un fichier .dockerignore pour exclure des fichiers de votre image de conteneur. Pour empêcher l'importation de fichiers dans Cloud Build, ajoutez un fichier .gcloudignore supplémentaire.

Dockerfile
    README.md
    *.pyc
    *.pyo
    *.pyd
    __pycache__
    

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 AdoptOpenJDK for base image.
    # It's important to use OpenJDK 8u191 or above that has container support enabled.
    # https://hub.docker.com/r/adoptopenjdk/openjdk8
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim

    # 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","-Dserver.port=${PORT}","-jar","/helloworld.jar"]
    

C#

# Use Microsoft's official build .NET image.
    # https://hub.docker.com/_/microsoft-dotnet-core-sdk/
    FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine AS build
    WORKDIR /app

    # Install production dependencies.
    # Copy csproj and restore as distinct layers.
    COPY *.csproj ./
    RUN dotnet restore

    # Copy local code to the container image.
    COPY . ./
    WORKDIR /app

    # Build a release artifact.
    RUN dotnet publish -c Release -o out

    # Use Microsoft's official runtime .NET image.
    # https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
    FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine AS runtime
    WORKDIR /app
    COPY --from=build /app/out ./

    # Run the web service on container startup.
    ENTRYPOINT ["dotnet", "helloworld-csharp.dll"]
    

Ajoutez un fichier .dockerignore pour exclure des fichiers de votre image de conteneur. Pour empêcher l'importation de fichiers dans Cloud Build, ajoutez un fichier .gcloudignore supplémentaire.

Dockerfile
    README.md
    **/obj/
    **/bin/

PHP

PHP Dockerfile démarre un serveur Web Apache, qui écoute sur le port défini par la variable d'environnement PORT :

# Use the official PHP 7.3 image.
    # https://hub.docker.com/_/php
    FROM php:7.3-apache

    # Copy local code to the container image.
    COPY index.php /var/www/html/

    # Use the PORT environment variable in Apache configuration files.
    RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf

    # Configure PHP for development.
    # Switch to the production php.ini for production operations.
    # RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
    # https://hub.docker.com/_/php#configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

    

Ajoutez un fichier .dockerignore pour exclure des fichiers de votre image de conteneur. Pour empêcher l'importation de fichiers dans Cloud Build, ajoutez un fichier .gcloudignore supplémentaire.

Dockerfile
    README.md
    vendor
    

Ruby

# Use the official lightweight Ruby image.
    # https://hub.docker.com/_/ruby
    FROM ruby:2.5-slim

    # Install production dependencies.
    WORKDIR /usr/src/app
    COPY Gemfile Gemfile.lock ./
    ENV BUNDLE_FROZEN=true
    RUN bundle install

    # Copy local code to the container image.
    COPY . ./

    # Run the web service on container startup.
    CMD ["ruby", "./app.rb"]
    

Shell

# 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:1.12 as builder

    # Copy local code to the container image.
    WORKDIR /go/src/github.com/knative/docs/helloworld-shell
    COPY invoke.go .

    # Build the 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 invoke

    # The official Alpine base image
    # https://hub.docker.com/_/alpine
    # 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:3.10

    # Copy Go binary
    COPY --from=builder /go/src/github.com/knative/docs/helloworld-shell/invoke /invoke
    COPY script.sh .

    # Run the web service on container startup.
    CMD ["/invoke"]
    

Autre

Cloud Run est compatible avec la plupart des langages. Pour obtenir des exemples de fichiers Docker dans d'autres langages que ceux présentés dans ce tableau, consultez les pages :

Cependant, dans ces exemples, ne tenez pas compte des informations sur service.yaml et Docker Hub, car Cloud Run ne les utilise pas.

Créez votre image de conteneur à l'aide de Cloud Build. Pour cela, exécutez la commande suivante à partir du répertoire contenant le fichier Docker :

gcloud builds submit --tag gcr.io/PROJECT-ID/helloworld

[PROJECT-ID] correspond à l'ID de votre projet GCP. Vous pouvez y accéder en exécutant gcloud config get-value project.

Si l'opération réussit, un message SUCCESS contenant le nom de l'image (gcr.io/PROJECT-ID/helloworld) s'affiche. L'image est stockée dans Container Registry et peut être réutilisée si vous le souhaitez.

Déployer sur Cloud Run

Pour déployer l'image de conteneur, procédez comme suit :

  1. Utilisez la commande suivante pour effectuer le déploiement :

    gcloud run deploy --image gcr.io/PROJECT-ID/helloworld --platform managed

    Remplacez [PROJECT_ID] par l'ID de votre projet GCP. Vous pouvez afficher l'ID de votre projet en exécutant la commande gcloud config get-value project.

    1. Vous serez invité à saisir le nom du service : appuyez sur Entrée pour accepter le nom par défaut, helloworld.
    2. Vous êtes invité à indiquer la région : sélectionnez la région de votre choix, par exemple us-central1.
    3. Vous êtes invité à autoriser les appels non authentifiés : répondez y .

    Patientez quelques instants jusqu'à la fin du déploiement. En cas de réussite, la ligne de commande affiche l'URL du service.

  2. Accédez à votre conteneur déployé en ouvrant l'URL du service dans un navigateur Web.

Emplacements Cloud Run

Cloud Run est régional, ce qui signifie que l'infrastructure qui exécute vos services Cloud Run est située dans une région spécifique et gérée par Google pour être disponible de manière redondante dans toutes les zones de cette région.

Lors de la sélection de la région dans laquelle exécuter vos services Cloud Run, vous devez tout d'abord considérer vos exigences en termes de latence, de disponibilité et de durabilité. Vous pouvez généralement sélectionner la région la plus proche de vos utilisateurs, mais vous devez tenir compte de l'emplacement des autres produits Google Cloud utilisés par votre service Cloud Run. L'utilisation combinée de produits Google Cloud sur plusieurs emplacements peut affecter la latence de votre service, ainsi que son coût.

Cloud Run est disponible dans les régions suivantes :

  • asia-east1 (Taïwan)
  • asia-northeast1 (Tokyo)
  • europe-north1 (Finlande)
  • europe-west1 (Belgique)
  • europe-west4 (Pays-Bas)
  • us-central1 (Iowa)
  • us-east1 (Caroline du Sud)
  • us-east4 (Virginie du Nord)
  • us-west1 (Oregon)

Si vous avez déjà créé un service Cloud Run, vous pouvez afficher la région dans le tableau de bord Cloud Run de Cloud Console.

Félicitations ! Vous venez de déployer une application empaquetée dans une image de conteneur sur Cloud Run. Cloud Run effectue un scaling automatique et horizontal de votre image de conteneur pour traiter les requêtes reçues, puis évolue à la baisse lorsque la demande diminue. Vous ne payez que pour le processeur, la mémoire et le réseau utilisés lors du traitement des requêtes.

Nettoyer

Supprimer votre projet test

Bien que Cloud Run ne facture pas lorsque le service n'est pas utilisé, il se peut que des frais vous soient facturés pour le stockage de l'image de conteneur dans Container Registry. Vous pouvez supprimer votre image ou votre projet Cloud afin d'éviter des frais. La suppression de votre projet Google Cloud arrête la facturation de toutes les ressources utilisées dans ce projet.

  1. Dans Cloud Console, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Étape suivante

Pour savoir comment créer un conteneur à partir d'un code source et le transférer dans Container Registry, reportez-vous à la page :