Use Docker e Docker Compose para implantar e executar perfeitamente seus aplicativos Nest.js.

A piada do desenvolvedor "Mas funciona no meu computador..." destaca perfeitamente o desafio de implantar e executar aplicativos em diferentes sistemas.

O verdadeiro incômodo está em configurar as dependências necessárias e garantir que as versões do software sejam compatíveis com seu aplicativo. Uma ótima solução alternativa para esse problema envolve o uso de tecnologia de conteinerização como o Docker.

Ele permite implantar e executar aplicativos sem esforço — com todas as dependências necessárias — dentro da imagem do contêiner; eliminando a necessidade de configuração extensiva em sistemas de produção.

Compreendendo o Docker e o Docker Compose

Docker é uma plataforma de desenvolvimento de código aberto que fornece tecnologia de conteinerização usada na construção e empacotamento de aplicativos junto com suas dependências como imagens portáteis.

Essas imagens são então executadas como componentes executáveis ​​em ambientes de contêiner isolados. A execução de aplicativos nesses contêineres garante um desempenho consistente dos aplicativos em diferentes sistemas de produção, sem problemas de compatibilidade.

Por outro lado, Docker Compose é uma ferramenta que é usado junto com o Docker para simplificar o processo de definição e gerenciamento de aplicativos multicontêineres.

Embora o Docker seja usado principalmente para gerenciar contêineres individuais, o Docker Compose permite gerenciar a configuração de vários contêineres que precisam ser executados como um único aplicativo.

Isto é particularmente útil quando uma aplicação consiste em vários serviços que precisam trabalhar juntos, como vários serviços de API dependentes e bancos de dados, entre outros.

Antes de mergulhar no código, você precisa instalar Área de Trabalho Docker em sua máquina local. Siga os requisitos específicos do sistema e as etapas de instalação da documentação oficial.

Você pode encontrar o código deste aplicativo em seu GitHub repositório.

Configurar um projeto Nest.js

Este guia orientará você no processo de criação de dois contêineres Docker que funcionam perfeitamente como um único aplicativo Nest.js. O primeiro contêiner conterá uma instância da imagem Docker do servidor web Nest.js, enquanto o segundo contêiner executará a imagem do banco de dados PostgreSQL do Docker.

Para começar, instale a ferramenta de linha de comando Nest.js:

npm i -g @nestjs/cli

Agora, crie um novo projeto Nest.js executando o comando abaixo em seu terminal.

nest new docker-nest-app

A seguir, a ferramenta CLI exibirá vários gerenciadores de pacotes para você escolher para criar o projeto. Escolha sua opção preferida. Neste caso, usaremos npm, o gerenciador de pacotes do nó.

Por último, você pode navegar até o diretório do projeto e ativar o servidor de desenvolvimento.

cd docker-nest-app
npm run start

Crie o módulo de banco de dados

Primeiro, instale estas dependências:

npm install pg typeorm @nestjs/typeorm @nestjs/config

A seguir, no diretório raiz do seu projeto, crie um .env arquivo e adicione os seguintes valores de configuração de conexão com o banco de dados:

DATABASE_HOST="db"
DATABASE_PORT=5432
DATABASE_USER="testUser"
DATABASE_PASSWORD="mypassword123"

Por último, vá em frente e crie o módulo de banco de dados.

nest g module database

Agora, após a criação do módulo, abra o banco de dados/banco de dados.module.ts arquivo e inclua o seguinte código de configuração do banco de dados:

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],
}),
],
})

exportclass DatabaseModule {}

Depois de configurar a imagem Docker PostgreSQL usando esta configuração TypeORM, o aplicativo Nest.js estabelecerá uma conexão com o banco de dados.

Atualize o arquivo app.module.ts

Por último, atualize o arquivo principal do módulo do aplicativo para incorporar a configuração do módulo de banco de dados.

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],
})

exportclass AppModule {}

Configurar um Dockerfile

Um Dockerfile captura o conjunto de instruções necessárias ao mecanismo Docker para criar uma imagem Docker. Esta imagem abrange o código-fonte do aplicativo e todas as suas dependências.

No diretório raiz do seu projeto, crie um novo arquivo e nomeie-o Dockerfile. Em seguida, adicione o seguinte conteúdo:

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" ]

Aqui está o que cada comando representa:

  1. DE: esta instrução especifica a imagem base que o Docker deve usar para construir a imagem da aplicação.
  2. DIRTRABALHO: Este comando instrui o Docker a definir o /app diretório como o diretório de trabalho do aplicativo dentro do contêiner.
  3. CÓPIA DEpacote*.json./: Copia todos os arquivos com esse formato de nome de arquivo do diretório atual no aplicativo para o aplicativo pasta.
  4. EXECUTAR instalação npm: Este comando instalará os pacotes e dependências necessários ao aplicativo dentro do contêiner Docker.
  5. CÓPIA DE. .: instrui o Docker a copiar todos os arquivos de código-fonte do aplicativo do diretório atual para o /app pasta.
  6. EXECUTAR npm executar compilação: o comando cria o aplicativo Nest.js antes de criar a imagem Docker. Ele compila o código TypeScript em JavaScript e armazena a saída do processo de construção em um distância diretório.
  7. DMC: define o comando a ser executado quando o contêiner for iniciado. Neste caso, executaremos o início de execução npm: dev comando, que iniciará o servidor em modo de desenvolvimento.

Essa configuração permite que o aplicativo monitore ativamente as alterações de código. Assim que as alterações forem detectadas, o contêiner passará automaticamente pela reconstrução.

Crie o arquivo Docker Compose

No diretório raiz da pasta do seu projeto, crie um novo docker-compose.yml arquivo e adicione o seguinte conteúdo:

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:

O Docker Compose usará estas instruções para construir e executar as duas imagens em dois contêineres Docker. O primeiro contêiner, o servidor, hospedará a imagem da aplicação; rodando na porta 3000.

O segundo contêiner hospedará a imagem do banco de dados PostgreSQL. Você não precisa especificar um Dockerfile para esta imagem – o Docker utilizará a imagem PostgreSQL pré-existente no registro de imagem do Docker para construí-la.

Inicie os contêineres Docker

Por fim, prossiga com a construção das imagens e inicie os contêineres executando o seguinte comando:

docker compose up

Assim que o processo for concluído com êxito, você deverá ver informações de log semelhantes em seu terminal.

Agora, com o servidor web e os contêineres de banco de dados em funcionamento, vá em frente e adicione mais funcionalidades ao seu aplicativo Nest.js. Por exemplo, você pode construir uma API REST CRUD Nest.js.

Enviando imagens do Docker para o Docker Hub

Enviar imagens do Docker para o Docker Hub é quase semelhante a enviar projetos para o GitHub. Siga estas etapas para enviar a imagem Docker do aplicativo Nest.js para o Docker Hub.

  1. Vá para DockerHub, inscreva-se e faça login na página de visão geral da sua conta.
  2. Clique no Criar repositório botão, preencha o nome do seu repositório, especifique sua visibilidade selecionando Público ou Privadoe clique em Criar.
  3. Agora, você precisa fazer login em sua conta através do terminal executando o comando abaixo e, em seguida, fornecer seu nome de usuário e senha do Docker.
    docker login
  4. A seguir, atualize o nome da imagem do Docker para corresponder a este formato: / executando o comando abaixo.
    docker tag /
  5. Por último, envie a imagem Docker.
    docker push /

Utilizando a tecnologia de conteinerização do Docker no desenvolvimento

A tecnologia de conteinerização do Docker permite agrupar um aplicativo junto com todas as suas dependências em imagens Docker. Essas imagens podem então ser executadas sem problemas em contêineres em diferentes ambientes de desenvolvimento e produção, sem problemas.