Pourquoi Deployer NestJS sur Azure ?
Le déploiement d'une application NestJS sur Azure offre plusieurs avantages. En effet, Azure fournit une infrastructure robuste et scalable pour gérer des applications en production. Il permet de bénéficier d'un haut niveau de disponibilité grâce à ses services automatiques de redondance et de mise à jour.
Un cas concret est le déploiement d'une application de gestion de tâches ou d'une API de blog, où un service cloud réduit les préoccupations liées à la maintenance serveur, le scaling et la sécurité des données. En déployant sur Azure, vous pouvez vous concentrer directement sur la construction et l'optimisation de votre application sans être contrainte par les aspects technique du support.
Prerequis
Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :
- Un compte Azure
- Node.js v14.x ou supérieur
- npm (Node Package Manager)
- Git
- Visual Studio Code (optionnel)
Concepts fondamentaux
1. Création d'un projet NestJS
La première étape consiste à créer un nouveau projet NestJS. Utilisez la commande suivante :
nest new my-nestjs-app
Cela créera un nouveau dossier my-nestjs-app avec les fichiers de base d'une application NestJS.
2. Configuration du fichier app.module.ts
Le fichier app.module.ts est le cœur de votre application NestJS. Il définit les modules, les contrôleurs et les fournisseurs nécessaires pour démarrer l'application.
// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
3. Définition d'un contrôleur
Un contrôleur gère les requêtes HTTP et retourne des réponses. Voici un exemple simple :
// src/app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
4. Fournisseurs et services
Les fournisseurs et les services contiennent la logique métier de votre application. Voici un exemple d'un service simple :
// src/app.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
5. Création d'une base de données avec PostgreSQL sur Azure
Azure offre un service PaaS (Platform as a Service) appelé Azure Database for PostgreSQL, qui permet de créer et gérer une instance de base de données PostgreSQL.
- Connectez-vous à l'portal Azure.
- Cliquez sur "Créer une ressource" et choisissez "Bases de données".
- Sélectionnez "Azure Database pour PostgreSQL" et suivez les instructions pour créer une instance.
6. Configuration de la connexion à la base de données
Dans votre application NestJS, configurez la connexion à la base de données en utilisant un module d'entité.
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'your-postgresql-server.database.windows.net',
port: 5432,
username: 'your-username',
password: 'your-password',
database: 'your-database',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
TypeOrmModule.forFeature([YourEntity]),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Mise en pratique : projet fil rouge
1. Création d'un gestionnaire de tâches
Étape 1 : Créer le modèle Entity
Créez un fichier task.entity.ts pour définir l'entité Task.
// src/task/task.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class Task {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column({ default: false })
completed: boolean;
}
Étape 2 : Créer le service
Créez un fichier task.service.ts pour définir les fonctionnalités du service.
// src/task/task.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Task } from './task.entity';
@Injectable()
export class TaskService {
constructor(
@InjectRepository(Task)
private readonly taskRepository: Repository<Task>,
) {}
findAll(): Promise<Task[]> {
return this.taskRepository.find();
}
findOne(id: number): Promise<Task> {
return this.taskRepository.findOne(id);
}
async create(task: Task): Promise<Task> {
return this.taskRepository.save(task);
}
async update(id: number, task: Task): Promise<Task> {
await this.taskRepository.update(id, task);
return this.taskRepository.findOne(id);
}
async remove(id: number): Promise<void> {
await this.taskRepository.delete(id);
}
}
Étape 3 : Créer le contrôleur
Créez un fichier task.controller.ts pour définir les endpoints.
// src/task/task.controller.ts
import { Controller, Get, Post, Put, Delete, Body, Param } from '@nestjs/common';
import { TaskService } from './task.service';
import { Task } from './task.entity';
@Controller('tasks')
export class TaskController {
constructor(private readonly taskService: TaskService) {}
@Get()
findAll(): Promise<Task[]> {
return this.taskService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string): Promise<Task> {
return this.taskService.findOne(+id);
}
@Post()
create(@Body() task: Task): Promise<Task> {
return this.taskService.create(task);
}
@Put(':id')
update(@Param('id') id: string, @Body() task: Task): Promise<Task> {
return this.taskService.update(+id, task);
}
@Delete(':id')
remove(@Param('id') id: string): Promise<void> {
return this.taskService.remove(+id);
}
}
Étape 4 : Ajouter les importations et exporter le module
Ajoutez les imports nécessaires dans app.module.ts pour que l'application puisse utiliser le contrôleur, le service et l'entité.
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TaskController } from './task/task.controller';
import { TaskService } from './task/task.service';
import { TaskEntity } from './task/task.entity';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'your-postgresql-server.database.windows.net',
port: 5432,
username: 'your-username',
password: 'your-password',
database: 'your-database',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
TypeOrmModule.forFeature([TaskEntity]),
],
controllers: [AppController, TaskController],
providers: [AppService, TaskService],
})
export class AppModule {}
2. Exécution de l'application
Exécutez votre application NestJS en utilisant la commande suivante :
npm run start
Votre API est maintenant accessible à http://localhost:3000/tasks.
Erreurs frequentes et debugging
1. Erreur : "Error: connect ECONNREFUSED"
Code incorrect :
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'your-username',
password: 'your-password',
database: 'your-database',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Code correct :
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'your-postgresql-server.database.windows.net',
port: 5432,
username: 'your-username',
password: 'your-password',
database: 'your-database',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
2. Erreur : "Error: Cannot find module 'typeorm'"
Code incorrect :
npm install typeorm --save
Code correct :
npm install @nestjs/typeorm typeorm pg --save
3. Erreur : "Error: listen EACCES: permission denied"
Code incorrect :
// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
Code correct :
// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT || 3000);
}
bootstrap();
Pour aller plus loin
1. Utiliser Docker pour déployer sur Azure
Docker permet de containeriser votre application, facilitant le déploiement et la mise à l'échelle.
- Créer un fichier
Dockerfiledans le répertoire racine :
## Use an official Node runtime as a parent image
FROM node:14
## Set the working directory in the container
WORKDIR /usr/src/app
## Copy package.json and package-lock.json
COPY package*.json ./
## Install any needed packages specified in package.json
RUN npm install
## Bundle app source inside Docker image
COPY . .
## Make port 3000 available to the world outside this container
EXPOSE 3000
## Define environment variable
ENV NAME World
## Run app.py when the container launches
CMD ["npm", "run", "start"]
- Créer un fichier
docker-compose.yml:
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
- Déployer sur Azure Container Instances (ACI) :
az container create --resource-group my-resource-group --name my-nestjs-app --image my-docker-image --ports 80 --restart-policy Always
2. Utiliser Azure Functions pour intégrer avec d'autres services
Azure Functions permet de créer des fonctions serverless qui peuvent être déclenchées par différents événements.
- Créer une fonction avec le CLI Azure :
func init MyFunctionApp --worker-runtime node
cd MyFunctionApp
func new --name HttpExample --template "HTTP trigger" --authlevel "anonymous"
- Ajouter la logique métier dans
HttpExample/index.jset déployer sur Azure Functions.
3. Utiliser Azure App Service pour déployer votre application
Azure App Service offre un service PaaS pour héberger des applications web, API et back-end basé sur le langage de programmation que vous choisissez.
- Créer une application Web dans le portail Azure.
- Déployer l'application NestJS en utilisant Git :
git init
git add .
git commit -m "Initial commit"
git remote add azure https://my-nestjs-app.scm.azurewebsites.net/my-nestjs-app.git
git push azure master
Défi pratique : Créer une API de blog
Créez une API de blog en utilisant NestJS, TypeORM et PostgreSQL. Votre application doit permettre de créer, lire, mettre à jour et supprimer des articles.
- Créer les entités
ArticleetComment. - Implémenter les services pour gérer ces entités.
- Créer les contrôleurs pour exposer les endpoints REST.
- Tester l'API en utilisant Postman ou un client HTTP.
En suivant ce tutoriel, vous devriez être capable de déployer une application NestJS sur Azure et la mettre à l'échelle pour gérer des charges de travail importantes.