Déployer une application Next.js full stack sur Cloud Run avec Firestore à l'aide du SDK administrateur Node.js

Déployer une application Next.js full stack sur Cloud Run avec Firestore à l'aide du SDK administrateur Node.js

À propos de cet atelier de programmation

subjectDernière mise à jour : avr. 11, 2025
account_circleRédigé par Luke Schlangen

1. Présentation

Cloud Run est une plate-forme entièrement gérée qui vous permet d'exécuter votre code directement sur l'infrastructure évolutive de Google. Cet atelier de programmation explique comment connecter une application Next.js sur Cloud Run à une base de données Firestore à l'aide du SDK Admin Node.js.

Dans cet atelier, vous allez apprendre à effectuer les tâches suivantes :

  • Créer une base de données Firestore
  • Déployer une application sur Cloud Run qui se connecte à votre base de données Firestore

2. Prérequis

  1. Si vous ne possédez pas encore de compte Google, vous devez en créer un.
    • Vous utilisez un compte personnel au lieu d'un compte professionnel ou scolaire. Les comptes professionnels et scolaires peuvent être soumis à des restrictions qui vous empêchent d'activer les API nécessaires à cet atelier.

3. Configuration du projet

  1. Connectez-vous à la console Google Cloud.
  2. Activez la facturation dans la console Cloud.
    • La réalisation de cet atelier devrait coûter moins de 1 USD en ressources Cloud.
    • Vous pouvez suivre les étapes à la fin de cet atelier pour supprimer les ressources afin d'éviter que des frais supplémentaires ne vous soient facturés.
    • Les nouveaux utilisateurs peuvent bénéficier d'un essai sans frais pour bénéficier d'un crédit de 300$.
  3. Créez un projet ou choisissez de réutiliser un projet existant.

4. Ouvrir l'éditeur Cloud Shell

  1. Accédez à l'éditeur Cloud Shell.
  2. Si le terminal ne s'affiche pas en bas de l'écran, ouvrez-le:
    • Cliquez sur le menu hamburger Icône du menu hamburger.
    • Cliquez sur Terminal
    • Cliquez sur Nouveau terminalOuvrir un nouveau terminal dans l'éditeur Cloud Shell
  3. Dans le terminal, définissez votre projet à l'aide de la commande suivante:
    • Format :
      gcloud config set project [PROJECT_ID]
    • Exemple :
      gcloud config set project lab-project-id-example
    • Si vous ne vous souvenez pas de l'ID de votre projet:
      • Vous pouvez lister tous vos ID de projet avec:
        gcloud projects list | awk '/PROJECT_ID/{print $2}'
      Définir l'ID de projet dans le terminal de l'éditeur Cloud Shell
  4. Si vous y êtes invité, cliquez sur Autoriser pour continuer. Cliquez pour autoriser Cloud Shell
  5. Le message suivant doit s'afficher :
    Updated property [core/project].
    
    Si un WARNING s'affiche et que vous êtes invité à saisir Do you want to continue (Y/N)?, vous avez probablement saisi l'ID de projet de manière incorrecte. Appuyez sur N, puis sur Enter, puis réessayez d'exécuter la commande gcloud config set project.

5. Activer les API

Dans le terminal, activez les API:

gcloud services enable \
  firestore.googleapis.com \
  run.googleapis.com \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com

Si vous y êtes invité, cliquez sur Autoriser pour continuer. Cliquez pour autoriser Cloud Shell

L'exécution de cette commande peut prendre quelques minutes, mais un message semblable à celui-ci devrait s'afficher pour vous indiquer que l'opération s'est correctement déroulée:

Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.

6. Créer une base de données Firestore

  1. Exécuter la commande gcloud firestore databases create pour créer une base de données Firestore
    gcloud firestore databases create --location=nam5

7. Préparer l'application

Préparez une application Next.js qui répond aux requêtes HTTP.

  1. Pour créer un projet Next.js nommé task-app, utilisez la commande suivante :
    npx --yes create-next-app@15.2.4 task-app \
      --ts \
      --eslint \
      --tailwind \
      --no-src-dir \
      --turbopack \
      --app \
      --no-import-alias
  2. Remplacez le répertoire par task-app:
    cd task-app
  1. Installez firebase-admin pour interagir avec la base de données Firestore.
    npm install firebase-admin
  1. Ouvrez le fichier actions.ts dans l'éditeur Cloud Shell:
    cloudshell edit app/actions.ts
    Un fichier vide devrait maintenant s'afficher en haut de l'écran. C'est là que vous pouvez modifier ce fichier actions.ts. Montrer que le code se trouve dans la partie supérieure de l'écran
  2. Copiez le code suivant et collez-le dans le fichier actions.ts ouvert:
    'use server'
    import { initializeApp, applicationDefault, getApps } from 'firebase-admin/app';
    import { getFirestore } from 'firebase-admin/firestore';
    const credential = applicationDefault();

    // Only initialize app if it does not already exist
    if (getApps().length === 0) {
      initializeApp({ credential });
    }

    const db = getFirestore();
    const tasksRef = db.collection('tasks');

    type Task = {
      id: string;
      title: string;
      status: 'IN_PROGRESS' | 'COMPLETE';
      createdAt: number;
    };

    // CREATE
    export async function addNewTaskToDatabase(newTask: string) {
      await tasksRef.doc().create({
        title: newTask,
        status: 'IN_PROGRESS',
        createdAt: Date.now(),
      });
      return;
    }

    // READ
    export async function getTasksFromDatabase() {
      const snapshot = await tasksRef.orderBy('createdAt', 'desc').limit(100).get();
      const tasks = await snapshot.docs.map(doc => ({
        id: doc.id,
        title: doc.data().title,
        status: doc.data().status,
        createdAt: doc.data().createdAt,
      }));
      return tasks;
    }

    // UPDATE
    export async function updateTaskInDatabase(task: Task) {
      await tasksRef.doc(task.id).set(task);
      return;
    }

    // DELETE
    export async function deleteTaskFromDatabase(taskId: string) {
      await tasksRef.doc(taskId).delete();
      return;
    }
  1. Ouvrez le fichier page.tsx dans l'éditeur Cloud Shell:
    cloudshell edit app/page.tsx
    Un fichier existant devrait maintenant s'afficher en haut de l'écran. C'est là que vous pouvez modifier ce fichier page.tsx. Montrer que le code se trouve dans la partie supérieure de l'écran
  2. Supprimez le contenu existant du fichier page.tsx.
  3. Copiez le code suivant et collez-le dans le fichier page.tsx ouvert:
    'use client'
    import React, { useEffect, useState } from "react";
    import { addNewTaskToDatabase, getTasksFromDatabase, deleteTaskFromDatabase, updateTaskInDatabase } from "./actions";

    type Task = {
      id: string;
      title: string;
      status: 'IN_PROGRESS' | 'COMPLETE';
      createdAt: number;
    };

    export default function Home() {
      const [newTaskTitle, setNewTaskTitle] = useState('');
      const [tasks, setTasks] = useState<Task[]>([]);

      async function getTasks() {
        const updatedListOfTasks = await getTasksFromDatabase();
        setTasks(updatedListOfTasks);
      }

      useEffect(() => {
        getTasks();
      }, []);

      async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
        e.preventDefault();
        await addNewTaskToDatabase(newTaskTitle);
        await getTasks();
        setNewTaskTitle('');
      };

      async function updateTask(task: Task, newTaskValues: Partial<Task>) {
        await updateTaskInDatabase({ ...task, ...newTaskValues });
        await getTasks();
      }

      async function deleteTask(taskId: string) {
        await deleteTaskFromDatabase(taskId);
        await getTasks();
      }

      return (
        <main className="p-4">
          <h2 className="text-2xl font-bold mb-4">To Do List</h2>
          <div className="flex mb-4">
            <form onSubmit={handleSubmit} className="flex mb-8">
              <input
                type="text"
                placeholder="New Task Title"
                value={newTaskTitle}
                onChange={(e) => setNewTaskTitle(e.target.value)}
                className="flex-grow border border-gray-400 rounded px-3 py-2 mr-2 bg-inherit"
              />
              <button
                type="submit"
                className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-nowrap"
              >
                Add New Task
              </button>
            </form>
          </div>
          <table className="w-full">
            <tbody>
              {tasks.map(function (task) {
                const isComplete = task.status === 'COMPLETE';
                return (
                  <tr key={task.id} className="border-b border-gray-200">
                    <td className="py-2 px-4">
                      <input
                        type="checkbox"
                        checked={isComplete}
                        onChange={() => updateTask(task, { status: isComplete ? 'IN_PROGRESS' : 'COMPLETE' })}
                        className="transition-transform duration-300 ease-in-out transform scale-100 checked:scale-125 checked:bg-green-500"
                      />
                    </td>
                    <td className="py-2 px-4">
                      <span
                        className={`transition-all duration-300 ease-in-out ${isComplete ? 'line-through text-gray-400 opacity-50' : 'opacity-100'}`}
                      >
                        {task.title}
                      </span>
                    </td>
                    <td className="py-2 px-4">
                      <button
                        onClick={() => deleteTask(task.id)}
                        className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded float-right"
                      >
                        Delete
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </main>
      );
    }

L'application est maintenant prête à être déployée.

8. Déployer l&#39;application dans Cloud Run

  1. Exécutez la commande ci-dessous pour déployer votre application sur Cloud Run:
    gcloud run deploy helloworld \
      --region=us-central1 \
      --source=.
  2. Si vous y êtes invité, appuyez sur Y et Enter pour confirmer que vous souhaitez continuer:
    Do you want to continue (Y/n)? Y
    

Après quelques minutes, l'application doit vous fournir une URL à laquelle vous pouvez accéder.

Accédez à l'URL pour voir votre application en action. Chaque fois que vous accéderez à l'URL ou actualiserez la page, l'application de tâches s'affichera.

9. Félicitations

Dans cet atelier, vous avez appris à effectuer les tâches suivantes :

  • Créer une instance Cloud SQL pour PostgreSQL
  • Déployer une application sur Cloud Run qui se connecte à votre base de données Cloud SQL

Effectuer un nettoyage

Cloud SQL ne propose pas de niveau sans frais et vous sera facturé si vous continuez à l'utiliser. Vous pouvez supprimer votre projet Cloud pour éviter des frais supplémentaires.

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 Artifact Registry. La suppression de votre projet Cloud arrête la facturation de toutes les ressources utilisées dans ce projet.

Si vous le souhaitez, supprimez le projet:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

Vous pouvez également supprimer les ressources inutiles de votre disque cloudshell. Vous pouvez :

  1. Supprimez le répertoire du projet de l'atelier de programmation:
    rm -rf ~/task-app
  2. Avertissement ! Cette action est irréversible. Si vous souhaitez supprimer tout ce qui se trouve sur votre Cloud Shell pour libérer de l'espace, vous pouvez supprimer l'intégralité de votre répertoire d'accueil. Assurez-vous que tout ce que vous souhaitez conserver est enregistré ailleurs.
    sudo rm -rf $HOME

Poursuivre votre apprentissage