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.

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 la page de sélection du projet de la console GCP, sélectionnez ou créez un projet GCP.

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

  3. Assurez-vous que la facturation est activée pour votre projet Google Cloud Platform. Découvrez comment confirmer que la facturation est activée pour votre projet.

  4. Activez l'API Cloud Run
  5. Installez et initialisez le SDK Cloud.
  6. Installez le composant gcloud bêta :
    gcloud components install beta
  7. 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. 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 contenant les éléments suivants :

    {
      "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 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.

Java

Créez une application Spring Boot.

  1. Installez le JDK Java SE 8 ou ultérieur et CURL. 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 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éé.

  3. Mettez à jour la classe HelloworldApplication dans src/main/java/com/example/helloworld/HelloworldApplication.java en ajoutant un @RestController pour gérer le mappage / et ajouter un champ @Value afin de fournir la variable d'environnement TARGET (cible) :

    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 2.2. 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. Modifiez le répertoire en helloworld-csharp.

  4. Mettez à jour la définition CreateWebHostBuilder dans Program.cs en spécifiant l'URL du port pour .UseUrls() afin de définir le port en service. L'exemple indique le port 8080, mais vous pouvez utiliser d'autres ports. Votre serveur doit écouter le port que vous spécifiez ici :

    using System;
    using Microsoft.AspNetCore;
    using Microsoft.AspNetCore.Hosting;
    
    namespace helloworld_csharp
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args)
            {
                string port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
                string url = String.Concat("http://0.0.0.0:", port);
    
                return WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>().UseUrls(url);
            }
        }
    }
    
  5. Mettez à jour l'instruction app.Run(...) dans Startup.cs pour lire et renvoyer la variable d'environnement TARGET :

    using System;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    
    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, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.Run(async (context) =>
                {
                    var target = Environment.GetEnvironmentVariable("TARGET") ?? "World";
                    await context.Response.WriteAsync($"Hello {target}\n");
                });
            }
        }
    }
    

    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.

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

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 fichier nommé Gemfile et copiez-y les éléments suivants :

    source 'https://rubygems.org'
    
    gem 'sinatra'
    gem 'rack', '>= 2.0.6'
    
  4. Créez un fichier nommé Gemfile.lock et copiez-y les éléments suivants :

    GEM
      remote: https://rubygems.org/
      specs:
        mustermann (1.0.2)
        rack (2.0.6)
        rack-protection (2.0.3)
          rack
        sinatra (2.0.3)
          mustermann (~> 1.0)
          rack (~> 2.0)
          rack-protection (= 2.0.3)
          tilt (~> 2.0)
        tilt (2.0.8)
    
    PLATFORMS
      ruby
    
    DEPENDENCIES
      rack (>= 2.0.6)
      sinatra
    
    BUNDLED WITH
       1.17.1
    

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 contenant les éléments suivants :

    #!/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 contenant les éléments suivants :

    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 relatives à 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 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
COPY . .

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

# 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 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 Python image.
# https://hub.docker.com/_/python
FROM python:3.7

# 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

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 .NET image.
# https://hub.docker.com/r/microsoft/dotnet
FROM microsoft/dotnet:2.2-sdk

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

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

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

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

PHP

# Use the official PHP 7.2 image.
# https://hub.docker.com/_/php
FROM php:7.2-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"

Ruby

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

# 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

FROM golang:1.11

WORKDIR /go/src/invoke

COPY invoke.go .
RUN go install -v

COPY . .

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 relatives à 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] est l'ID de votre projet GCP. Vous pouvez l'obtenir en exécutant la commande gcloud config get-value project.

En cas de réussite, un message SUCCESS apparaît contenant le nom de l’image (gcr.io/[PROJECT-ID]/helloworld). Celle-ci 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 :

    Par défaut

    gcloud beta run deploy --image gcr.io/[PROJECT-ID]/helloworld
    

    Java

    gcloud beta run deploy --image gcr.io/[PROJECT-ID]/helloworld \
          --set-env-vars="JAVA_TOOL_OPTIONS=-XX:MaxRAM=256m"
    

    L'attribution de la variable d'environnement JAVA_TOOL_OPTIONS=-XX:MaxRAM=256m corrige un problème connu lié à la mémoire JVM.

    [PROJECT-ID] est l'ID de votre projet GCP. Vous pouvez l'obtenir en exécutant la commande gcloud config get-value project.

    Lorsque vous y êtes invité, sélectionnez une région (par exemple, us-central1), confirmez le nom du service, puis indiquez la réponse y pour autoriser les appels non authentifiés.

    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.

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.

Effectuer un nettoyage

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 GCP afin d'éviter des frais. La suppression de votre projet GCP arrête la facturation de toutes les ressources utilisées dans ce projet.

  1. Dans la console GCP, 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 :

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…