Hur man containeriserar Nest.js-applikationer med Docker och Docker Compose
“Men det fungerar på min dator…” utvecklarskämtet belyser perfekt utmaningen med att distribuera och köra applikationer över olika system.
Att navigera genom komplexiteten i beroendekonfiguration och versionskompatibilitet kan vara en skrämmande uppgift för utvecklare. Det finns dock ett effektivt tillvägagångssätt som kan lindra dessa utmaningar genom att använda containeriseringstekniker som Docker. Detta tillvägagångssätt förenklar processen genom att kapsla in alla nödvändiga komponenter i en fristående miljö, vilket minskar potentiella konflikter och effektiviserar distributionsprocesserna.
Plattformen gör det möjligt för användare att sömlöst distribuera och köra applikationer, tillsammans med deras nödvändiga komponenter, i en containeriserad miljö, vilket gör att man slipper komplicerade installationsprocedurer i produktionsmiljöer.
Förstå Docker och Docker Compose
Docker är en utvecklingsplattform med öppen källkod som tillhandahåller containeriseringsteknik som används för att bygga och paketera applikationer tillsammans med deras beroenden som portabla avbildningar.
De ovan nämnda bilderna körs därefter i form av körbara moduler i fristående fartygsmiljöer. Användningen av applikationer inom sådana gränser säkerställer enhetlighet när det gäller prestanda för olika produktionsplattformar, utan några potentiella avvikelser eller hinder för interoperabilitet.
Docker Compose fungerar som ett extra instrument när det används tillsammans med Docker, vilket underlättar effektiviseringen av installations- och hanteringsprocesser för multicontainertillämpningar.
Docker Compose utökar Dockers funktionalitet genom att möjliggöra hantering av flera containrar som tillsammans bildar en enskild applikation.
Detta tillvägagångssätt är särskilt fördelaktigt i scenarier där en mjukvaruapplikation omfattar flera ömsesidigt beroende tjänster, inklusive men inte begränsat till olika databassystem, samt flera API-tjänster med ömsesidiga beroenden.
Innan du dyker ner i koden måste du installera Docker Desktop på din lokala dator. Gå igenom de systemspecifika kraven och installationsstegen i den officiella dokumentationen.
Man kan hitta källkoden för denna programvara i dessGitHub-förvar, som fungerar som ett digitalt arkiverings- och versionshanteringssystem för att spåra ändringar i programmet över tiden.
Konfigurera ett Nest.js-projekt
Denna handledning beskriver proceduren för att distribuera två Docker-containrar i tandem för att fungera som en enhetlig Nest.js-applikation. Den första behållaren ska vara värd för en instansiering av Nest.js webbserver Docker-image, och den efterföljande behållaren ska köra Dockers PostgreSQL-databasimage.
För att initiera processen är det nödvändigt att installera Nest.js Command Line Interface (CLI) utility. Detta kommer att ge ett bekvämt sätt att interagera med ditt projekt och utföra olika kommandon från terminalen.
npm i -g @nestjs/cli
För att skapa ett nytt Nest.js-projekt med hjälp av terminalen, kör följande kommando i terminalfönstret:
nest new docker-nest-app
När du väljer “Skapa projekt” visas en lista över tillgängliga pakethanterare. Välj önskad pakethanterare. För exemplets skull väljer vi “npm”, som är Node Package Manager.
Slutligen kan du navigera till projektets katalog och starta utvecklingsservern.
cd docker-nest-app
npm run start
Skapa databasmodulen
Installera först dessa beroenden:
npm install pg typeorm @nestjs/typeorm @nestjs/config
Skapa en “.env”-fil i den primära katalogen för ditt projekt och infoga de efterföljande konfigurationerna för databasanslutningen:
DATABASE_HOST="db"
DATABASE_PORT=5432
DATABASE_USER="testUser"
DATABASE_PASSWORD="mypassword123"
Fortsätt slutligen med att skapa databasmodulen.
nest g module database
När du har skapat en ny modul i Visual Studio Code öppnar du filen “database/database.module.ts” och infogar den efterföljande koden för databasinställningar enligt följande:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
type: 'postgres',
host: configService.get<string>('DATABASE_HOST'),
port: configService.get<number>('DATABASE_PORT'),
username: configService.get<string>('DATABASE_USER'),
password: configService.get<string>('DATABASE_PASSWORD'),
synchronize: true,
}),
inject: [ConfigService],
}),
],
})
export class DatabaseModule {}
När du har implementerat den angivna Docker PostgreSQL-konfigurationen i din TypeORM-installation, ska din Nest.js-applikation lyckas ansluta till databasen.
Uppdatera filen app.module.ts
Slutligen, modifiera den primära applikationsmodulfilen för att integrera inställningarna för databasmodulen.
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
}),
DatabaseModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Konfigurera en Dockerfil
En Dockerfil fungerar som en ritning som anger de nödvändiga stegen för att konstruera en Docker-avbildning, som innehåller programmets källkod tillsammans med alla dess nödvändiga beroenden.
Skapa ett nytt dokument i den primära mappen för ditt projekt och ge det namnet “Dockerfile”. Införliva därefter följande beståndsdelar inom dess område:
FROM node:16.3.0-alpine3.13
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD [ "npm", "run", "start:dev" ]
Här är vad varje kommando representerar:
Ovanstående direktiv anger den grund på vilken Docker instrueras att konstruera programvarans visuella representation, känd som en image.
Det ovan nämnda direktivet anger att mappen /app
ska vara den aktiva arbetsytan för applikationens funktioner inom Docker-containerns gränser.
Filen package.json
kopierar automatiskt alla filer inom det angivna formatet från den aktuella projektkatalogen till mappen “app”, som en del av dess konfigurationsprocess.
Det ovannämnda steget innebär att kommandot “npm install” utförs, vilket underlättar installationen av alla nödvändiga paket och beroenden som krävs för att applikationen ska fungera korrekt inom Docker-containerns gränser.
Docker instrueras att replikera allt innehåll i den aktuella arbetskatalogens programkällfiler i den angivna underkatalogen ‘/app’, med hjälp av detta direktiv.
För att köra Nest.js-applikationen är det föreslagna steget att först initiera byggprocessen genom att köra kommandot npm run build
. Denna åtgärd innebär att TypeScript-källkoden transponeras till motsvarande JavaScript med hjälp av de angivna förinställningarna och plugins. Samtidigt skapas en optimerad bunt i mappen dist
för vidare distribution eller exekvering.
Den givna texten beskriver en Dockerfile-instruktion som anger kommandot som ska köras när behållaren startas. Specifikt styr den utförandet av ett npm run start:dev-kommando, som initierar servern i dess utvecklingsstatus.
Den ovan nämnda konfigurationen ger programvaran möjlighet att noggrant observera ändringar i källkoden. När eventuella ändringar identifieras är containern programmerad att initiera en automatisk rekonstruktionsprocess.
Skapa filen Docker Compose
I den primära katalogen i projektets arbetsyta ska du skapa ett nytt docker-compose.yml-dokument i katalogen. Lägg sedan till de efterföljande bestämmelserna i denna nyetablerade fil:
version: '3.9'
services:
server:
build: .
ports:
- '3000:3000'
depends_on:
- db
db:
image: 'postgres'
ports:
- '5432:5432'
environment:
POSTGRES_PASSWORD: 'mypassword123'
POSTGRES_USER: 'testUser'
volumes:
- data:/var/lib/postgresql/data
volumes:
data:
Docker Compose kommer att använda de angivna riktlinjerna för att konstruera och köra två Docker-avbildningar i två separata Docker-behållare. Den första containern, som kallas “server”, ska fungera som en plattform för applikationens image och kommer att vara åtkomlig via port 3000.
Den andra behållaren kommer att innehålla PostgreSQL-databasbilden, som kommer att konstrueras med hjälp av en befintlig PostgreSQL-bild från Dockers bildförråd. Ingen separat Docker-fil krävs eftersom de nödvändiga instruktionerna redan finns i den förbyggda bilden.
Starta Docker Containers
Sammanfattningsvis, för att konstruera avbildningarna och starta containrarna, kör följande kommando:
docker compose up
När processen har slutförts förväntas en jämförbar uppsättning loggdata visas i systemets terminalutmatning.
När både webbservern och databascontainrarna är i drift är det dags att utöka funktionerna i vår Nest.js-applikation ytterligare. En sådan förbättring skulle kunna vara att konstruera ett användarvänligt gränssnitt för att interagera med data som lagras i PostgreSQL-databasen med hjälp av ett CRUD (Create, Read, Update, Delete) RESTful API byggt på Nest.js-ramverket.
Pusha Docker-bilder till Docker Hub
Att överföra Docker-bilder till Docker Hub påminner mycket om att skicka in projekt till GitHub. Följ den här processen för att ladda upp Nest.js-applikationens Docker-image:
⭐ Gå över till Docker Hub , registrera dig och logga in på ditt kontos översiktssida.
⭐ Klicka på knappen Skapa repository, fyll i namnet på ditt repository, ange dess synlighet genom att välja antingen Public eller Private och klicka sedan på Skapa .
⭐ Nu måste du logga in på ditt konto via terminalen genom att köra kommandot nedan och sedan ange ditt Docker-användarnamn och lösenord.
docker login
⭐ Uppdatera sedan Dockers bildnamn så att det matchar det här formatet: / genom att köra kommandot nedan.
docker tag <image> <your docker username>/<repo name>
⭐ Slutligen pushar du Docker-avbildningen.
docker push <image>/<repo name>
Använda Dockers containeriseringsteknik i utveckling
Dockers containeriseringsfunktioner gör det möjligt att paketera applikationer, tillsammans med deras nödvändiga beroenden, i Docker-avbildningar. Detta säkerställer att dessa avbildningar fungerar sömlöst i olika utvecklings- och produktionsinställningar utan att stöta på några komplikationer eller kompatibilitetsproblem.