1. Übersicht
Cloud Run ist eine vollständig verwaltete Plattform, mit der Sie Ihren Code direkt auf der skalierbaren Infrastruktur von Google ausführen können. In diesem Codelab wird gezeigt, wie Sie eine Angular-Anwendung in Cloud Run über den Cloud SQL Node.js Connector mit einer Cloud SQL for PostgreSQL-Datenbank verbinden.
Aufgaben in diesem Lab:
- Cloud SQL for PostgreSQL-Instanz erstellen
- Anwendung in Cloud Run bereitstellen, die eine Verbindung zu Ihrer Cloud SQL-Datenbank herstellt
2. Vorbereitung
- Wenn Sie noch kein Google-Konto haben, müssen Sie ein Google-Konto erstellen.
- Verwenden Sie stattdessen ein privates Konto. Bei Arbeitskonten und Konten von Bildungseinrichtungen kann es Einschränkungen geben, die verhindern, dass Sie die für dieses Lab erforderlichen APIs aktivieren.
3. Projekt einrichten
- Melden Sie sich in der Google Cloud Console an.
- Aktivieren Sie die Abrechnung in der Cloud Console.
- Die Cloud-Ressourcen, die für dieses Lab benötigt werden, sollten weniger als 1 $kosten.
- Sie können die Schritte am Ende dieses Labs ausführen, um Ressourcen zu löschen und so weitere Kosten zu vermeiden.
- Neue Nutzer haben Anspruch auf die kostenlose Testversion mit einem Guthaben von 300$.
- Erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt wieder.
4. Cloud Shell-Editor öffnen
- Rufen Sie den Cloud Shell-Editor auf.
- Wenn das Terminal nicht unten auf dem Bildschirm angezeigt wird, öffnen Sie es:
- Klicken Sie auf das Dreistrich-Menü
. - Klicken Sie auf Terminal.
- Klicken Sie auf Neues Terminal
.
- Klicken Sie auf das Dreistrich-Menü
- Legen Sie im Terminal Ihr Projekt mit diesem Befehl fest:
- Format:
gcloud config set project [PROJECT_ID] - Beispiel:
gcloud config set project lab-project-id-example - Wenn Sie sich nicht an Ihre Projekt-ID erinnern können:
- Sie können alle Ihre Projekt-IDs mit folgendem Befehl auflisten:
gcloud projects list | awk '/PROJECT_ID/{print $2}'

- Sie können alle Ihre Projekt-IDs mit folgendem Befehl auflisten:
- Format:
- Wenn Sie zur Autorisierung aufgefordert werden, klicken Sie auf Autorisieren, um fortzufahren.

- Es sollte folgende Meldung angezeigt werden:
Wenn SieUpdated property [core/project].
WARNINGsehen undDo you want to continue (Y/N)?gefragt werden, haben Sie die Projekt-ID wahrscheinlich falsch eingegeben. Drücken SieN, dannEnterund versuchen Sie, den Befehlgcloud config set projectnoch einmal auszuführen.
5. APIs aktivieren
Aktivieren Sie die APIs im Terminal:
gcloud services enable \
sqladmin.googleapis.com \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com
Wenn Sie zur Autorisierung aufgefordert werden, klicken Sie auf Autorisieren, um fortzufahren. 
Es kann einige Minuten dauern, bis dieser Befehl ausgeführt wird. Wenn die Ausführung erfolgreich war, erhalten Sie eine Meldung, die ungefähr so aussieht:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
6. Dienstkonto einrichten
Erstellen und konfigurieren Sie ein Google Cloud-Dienstkonto, das von Cloud Run verwendet werden soll, damit es die richtigen Berechtigungen zum Herstellen einer Verbindung zu Cloud SQL hat.
- Führen Sie den Befehl
gcloud iam service-accounts createso aus, um ein neues Dienstkonto zu erstellen:gcloud iam service-accounts create quickstart-service-account \ --display-name="Quickstart Service Account" - Führen Sie den Befehl „gcloud projects add-iam-policy-binding“ wie unten beschrieben aus, um dem Google Cloud-Dienstkonto, das Sie gerade erstellt haben, die Rolle Cloud SQL-Client hinzuzufügen.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client" - Führen Sie den Befehl „gcloud projects add-iam-policy-binding“ wie unten beschrieben aus, um dem Google Cloud-Dienstkonto, das Sie gerade erstellt haben, die Rolle Cloud SQL-Instanznutzer hinzuzufügen.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role="roles/cloudsql.instanceUser" - Führen Sie den Befehl „gcloud projects add-iam-policy-binding“ wie unten beschrieben aus, um dem soeben erstellten Google Cloud-Dienstkonto die Rolle Logautor hinzuzufügen.
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role="roles/logging.logWriter"
7. Cloud SQL-Datenbank erstellen
- Führen Sie den Befehl
gcloud sql instances createaus, um eine Cloud SQL-Instanz zu erstellen.gcloud sql instances create quickstart-instance \ --database-version=POSTGRES_14 \ --cpu=4 \ --memory=16GB \ --region=us-central1 \ --database-flags=cloudsql.iam_authentication=on
Die Ausführung dieses Befehls kann einige Minuten dauern.
- Führen Sie den Befehl
gcloud sql databases createaus, um eine Cloud SQL-Datenbank in derquickstart-instancezu erstellen.gcloud sql databases create quickstart_db \ --instance=quickstart-instance - Erstellen Sie einen PostgreSQL-Datenbanknutzer für das Dienstkonto, das Sie zuvor erstellt haben, um auf die Datenbank zuzugreifen.
gcloud sql users create quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam \ --instance=quickstart-instance \ --type=cloud_iam_service_account
8. Anwendung vorbereiten
Bereiten Sie eine Next.js-Anwendung vor, die auf HTTP-Anfragen reagiert.
- Verwenden Sie den folgenden Befehl, um ein neues Next.js-Projekt mit dem Namen
task-appzu erstellen:npx --yes @angular/cli@19.2.5 new task-app \ --minimal \ --inline-template \ --inline-style \ --ssr \ --server-routing \ --defaults - Ändern Sie das Verzeichnis in
task-app:cd task-app
- Installieren Sie
pgund die Cloud SQL Node.js-Connector-Bibliothek, um mit der PostgreSQL-Datenbank zu interagieren.npm install pg @google-cloud/cloud-sql-connector google-auth-library - Installieren Sie
@types/pgals Entwicklungsabhängigkeit, um eine TypeScript-Next.js-Anwendung zu verwenden.npm install --save-dev @types/pg
- Öffnen Sie die Datei
server.tsim Cloud Shell-Editor: Oben auf dem Bildschirm sollte jetzt eine Datei angezeigt werden. Hier können Sie die Dateicloudshell edit src/server.tsserver.tsbearbeiten.
- Löschen Sie den vorhandenen Inhalt der Datei
server.ts. - Kopieren Sie den folgenden Code und fügen Sie ihn in die geöffnete Datei
server.tsein:import { AngularNodeAppEngine, createNodeRequestHandler, isMainModule, writeResponseToNodeResponse, } from '@angular/ssr/node'; import express from 'express'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import pg from 'pg'; import { AuthTypes, Connector } from '@google-cloud/cloud-sql-connector'; import { GoogleAuth } from 'google-auth-library'; const auth = new GoogleAuth(); const { Pool } = pg; type Task = { id: string; title: string; status: 'IN_PROGRESS' | 'COMPLETE'; createdAt: number; }; const projectId = await auth.getProjectId(); const connector = new Connector(); const clientOpts = await connector.getOptions({ instanceConnectionName: `${projectId}:us-central1:quickstart-instance`, authType: AuthTypes.IAM, }); const pool = new Pool({ ...clientOpts, user: `quickstart-service-account@${projectId}.iam`, database: 'quickstart_db', }); const tableCreationIfDoesNotExist = async () => { await pool.query(`CREATE TABLE IF NOT EXISTS tasks ( id SERIAL NOT NULL, created_at timestamp NOT NULL, status VARCHAR(255) NOT NULL default 'IN_PROGRESS', title VARCHAR(1024) NOT NULL, PRIMARY KEY (id) );`); } const serverDistFolder = dirname(fileURLToPath(import.meta.url)); const browserDistFolder = resolve(serverDistFolder, '../browser'); const app = express(); const angularApp = new AngularNodeAppEngine(); app.use(express.json()); app.get('/api/tasks', async (req, res) => { await tableCreationIfDoesNotExist(); const { rows } = await pool.query(`SELECT id, created_at, status, title FROM tasks ORDER BY created_at DESC LIMIT 100`); res.send(rows); }); app.post('/api/tasks', async (req, res) => { const newTaskTitle = req.body.title; if (!newTaskTitle) { res.status(400).send("Title is required"); return; } await tableCreationIfDoesNotExist(); await pool.query(`INSERT INTO tasks(created_at, status, title) VALUES(NOW(), 'IN_PROGRESS', $1)`, [newTaskTitle]); res.sendStatus(200); }); app.put('/api/tasks', async (req, res) => { const task: Task = req.body; if (!task || !task.id || !task.title || !task.status) { res.status(400).send("Invalid task data"); return; } await tableCreationIfDoesNotExist(); await pool.query( `UPDATE tasks SET status = $1, title = $2 WHERE id = $3`, [task.status, task.title, task.id] ); res.sendStatus(200); }); app.delete('/api/tasks', async (req, res) => { const task: Task = req.body; if (!task || !task.id) { res.status(400).send("Task ID is required"); return; } await tableCreationIfDoesNotExist(); await pool.query(`DELETE FROM tasks WHERE id = $1`, [task.id]); res.sendStatus(200); }); /** * Serve static files from /browser */ app.use( express.static(browserDistFolder, { maxAge: '1y', index: false, redirect: false, }), ); /** * Handle all other requests by rendering the Angular application. */ app.use('/**', (req, res, next) => { angularApp .handle(req) .then((response) => response ? writeResponseToNodeResponse(response, res) : next(), ) .catch(next); }); /** * Start the server if this module is the main entry point. * The server listens on the port defined by the `PORT` environment variable, or defaults to 4000. */ if (isMainModule(import.meta.url)) { const port = process.env['PORT'] || 4000; app.listen(port, () => { console.log(`Node Express server listening on http://localhost:${port}`); }); } /** * Request handler used by the Angular CLI (for dev-server and during build) or Firebase Cloud Functions. */ export const reqHandler = createNodeRequestHandler(app);
- Öffnen Sie die Datei
app.component.tsim Cloud Shell-Editor: Oben auf dem Bildschirm sollte jetzt eine vorhandene Datei angezeigt werden. Hier können Sie die Dateicloudshell edit src/app/app.component.tsapp.component.tsbearbeiten.
- Löschen Sie den vorhandenen Inhalt der Datei
app.component.ts. - Kopieren Sie den folgenden Code und fügen Sie ihn in die geöffnete Datei
app.component.tsein:import { afterNextRender, Component, signal } from '@angular/core'; import { FormsModule } from '@angular/forms'; type Task = { id: string; title: string; status: 'IN_PROGRESS' | 'COMPLETE'; createdAt: number; }; @Component({ selector: 'app-root', standalone: true, imports: [FormsModule], template: ` <section> <input type="text" placeholder="New Task Title" [(ngModel)]="newTaskTitle" class="text-black border-2 p-2 m-2 rounded" /> <button (click)="addTask()">Add new task</button> <table> <tbody> @for (task of tasks(); track task) { @let isComplete = task.status === 'COMPLETE'; <tr> <td> <input (click)="updateTask(task, { status: isComplete ? 'IN_PROGRESS' : 'COMPLETE' })" type="checkbox" [checked]="isComplete" /> </td> <td>{{ task.title }}</td> <td>{{ task.status }}</td> <td> <button (click)="deleteTask(task)">Delete</button> </td> </tr> } </tbody> </table> </section> `, styles: '', }) export class AppComponent { newTaskTitle = ''; tasks = signal<Task[]>([]); constructor() { afterNextRender({ earlyRead: () => this.getTasks() }); } async getTasks() { const response = await fetch(`/api/tasks`); const tasks = await response.json(); this.tasks.set(tasks); } async addTask() { await fetch(`/api/tasks`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: this.newTaskTitle, status: 'IN_PROGRESS', createdAt: Date.now(), }), }); this.newTaskTitle = ''; await this.getTasks(); } async updateTask(task: Task, newTaskValues: Partial<Task>) { await fetch(`/api/tasks`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...task, ...newTaskValues }), }); await this.getTasks(); } async deleteTask(task: any) { await fetch('/api/tasks', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(task), }); await this.getTasks(); } }
Die Anwendung kann jetzt bereitgestellt werden.
9. Anwendung in Cloud Run bereitstellen
- Führen Sie den folgenden Befehl aus, um die Anwendung in Cloud Run bereitzustellen:
gcloud run deploy to-do-tracker \ --region=us-central1 \ --source=. \ --service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --allow-unauthenticated - Wenn Sie dazu aufgefordert werden, drücken Sie
YundEnter, um zu bestätigen, dass Sie fortfahren möchten:Do you want to continue (Y/n)? Y
Nach einigen Minuten sollte die Anwendung eine URL bereitstellen, die Sie aufrufen können.
Rufen Sie die URL auf, um Ihre Anwendung in Aktion zu sehen. Jedes Mal, wenn Sie die URL aufrufen oder die Seite aktualisieren, wird die Aufgaben-App angezeigt.
10. Glückwunsch
In diesem Lab haben Sie Folgendes gelernt:
- Cloud SQL for PostgreSQL-Instanz erstellen
- Anwendung in Cloud Run bereitstellen, die eine Verbindung zu Ihrer Cloud SQL-Datenbank herstellt
Bereinigen
Cloud SQL bietet kein kostenloses Kontingent. Wenn Sie den Dienst weiterhin nutzen, werden Ihnen die Kosten in Rechnung gestellt. Sie können Ihr Cloud-Projekt löschen, um zusätzliche Gebühren zu vermeiden.
Während für Cloud Run keine Kosten anfallen, wenn der Dienst nicht verwendet wird, wird Ihnen dennoch das Speichern des Container-Images in Artifact Registry möglicherweise in Rechnung gestellt. Durch das Löschen des Cloud-Projekts wird die Abrechnung für alle in diesem Projekt verwendeten Ressourcen beendet.
Wenn Sie möchten, können Sie das Projekt löschen:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Sie können auch unnötige Ressourcen von Ihrer Cloud Shell-Festplatte löschen. Sie haben folgende Möglichkeiten:
- Löschen Sie das Codelab-Projektverzeichnis:
rm -rf ~/task-app - Warnung! Diese Aktion kann nicht rückgängig gemacht werden. Wenn Sie alles in Ihrer Cloud Shell löschen möchten, um Speicherplatz freizugeben, können Sie Ihr gesamtes Basisverzeichnis löschen. Achten Sie darauf, dass alles, was Sie behalten möchten, an einem anderen Ort gespeichert ist.
sudo rm -rf $HOME
Weiterlernen
- Vollständige Next.js-Anwendung mit Cloud SQL for PostgreSQL in Cloud Run bereitstellen
- Vollständige Angular-Anwendung in Cloud Run mit Cloud SQL for PostgreSQL mithilfe des Cloud SQL Node.js-Connectors bereitstellen
- Vollständige Angular-Anwendung mit Firestore in Cloud Run bereitstellen (mit dem Node.js Admin SDK)
- Full-Stack-Next.js-Anwendung mit Firestore und dem Node.js Admin SDK in Cloud Run bereitstellen