Construindo uma API com NestJS, PostgreSQL e Docker — Parte 7: Deploy!

Iago Maia Silva
8 min readMar 30, 2020

--

NestJS — Um framework Node.js para construção de aplicações confiáveis e escaláveis.

Recentemente comecei a estudar Node pensei em desenvolver uma API com funcionalidades básicas, que praticamente todo projeto precisa, como forma de me familiarizar com a linguagem. Para me auxiliar nessa tarefa utilizei o framework NestJS. Nesta série de tutoriais vou compartilhar o que aprendi.

Série completa:

Irei atualizando essa lista com links para as devidas partes conforme eu for postando!

Requisitos

O código da etapa anterior se encontra em um repositório no meu GitHub:

TL;DR

O código desta etapa também se encontra em um repositório no meu GitHub:

Deploy!

Enfim chegamos à última parte dessa série: Vamos colocar nossa API na nuvem! A primeira coisa que precisamos para colocar nossa API online é de um servidor onde hospedá-la. Nesse tutorial utilizarei os serviços da DigitalOcean. Caso ainda não tenha, você pode criar uma conta aqui. Criando uma conta através desse link você ganha $100 em créditos para serem gastos em 60 dias na plataforma.

Após criar sua conta e acessar a plataforma, vamos criar uma droplet. Droplets são a maneira como a DigitalOcean chama os servidores em nuvem (famosos VPS — Virtual Private Server).

Para criar um droplet clique no dropdown Create, no canto direito superior, e selecione “Droplets”, a primeira opção.

Criação de Droplets

Vamos agora selecionar o Sistema Operacional do nosso servidor:

Sistemas Operacionais disponíveis

Nesse tutorial vamos seguir com o Ubuntu mesmo. Entretanto, temos algumas outras opções de SO, dependendo das necessidades do seu sistema.

Reparem também na existência da aba “Marketplace”. Nela você encontra algumas imagens de criação de droplets que já vêm com uma série de funcionalidades, como o stack LAMP instalado, docker, Wordpress, entre várias outras coisas. Vale a pena conferir!

Escolhido a imagem de criação, vamos para a segunda etapa: A escolha do plano.

Para este tutorial vamos escolher o plano mais básico de todos, de $5/mês. Vale a pena dar uma olhada nos outros planos disponíveis para uso futuro.

Escolha de planos

A próxima etapa é opcional: Adicionar um Volume à nossa Droplet. Pense em um Volume como espaço adicional em disco para sua Droplet. No nosso caso os 25GB são mais do que suficiente.

Agora vamos escolher onde nosso servidor vai estar localizado. Infelizmente a DigitalOcean não possui um datacenter no Brasil, então vamos escolher algum nos EUA, que são os mais próximos:

Escolhendo localização

A próxima etapa também é opcional: Você pode escolher habilitar alguns recursos adicionais para sua Droplet, nesse caso não vamos habilitar nenhum deles.

Agora vamos escolher a forma pela qual ser autenticados para acessar nossa Droplet: podemos escolher autenticação via chave SSH ou usuário/senha. Nesse tutorial vou utilizar a chave SSH, mas vou explicar como ambos funcionam.

Caso você opte por usuário/senha você deve marcar a segunda opção:

Autenticação via usuário/senha

Escolhendo essa opção, ao finalizar a criação da Droplet você receberá no seu email uma senha para acessar a Droplet recém criada com o usuário root.

Caso opte por autenticação via chave SSH, deve escolher a primeira opção:

Autenticação via chave SSH

Repare no botão New SSH Key. É através dele que você adicionará uma chave SSH para ser utilizada na autenticação. Você pode aprender como criar uma chave SSH e utilizá-la como método de autenticação aqui.

Com sua chave SSH criada, basta ir na pasta onde você a salvou (normalmente ~/.ssh) e copiar o conteúdo da chave pública (possui extensão .pub, normalmente se chama id_rsa.pub, se você escolheu a opção padrão durante a criação) e colar esse mesmo conteúdo na janela que irá abrir ao clicar em New SSH Key. Você também deve dar um nome para identificar essa chave no painel da DigitalOcean.

Agora podemos finalizar a criação da nossa Droplet:

Etapa final para criação da Droplet

Você tem a opção de criar mais de uma Droplet com as mesmas configurações, bem como a opção de adicionar um nome mais amigável a ela (eu escolhi tutorial-medium, normalmente esse campo vem preenchido com um nome padrão gerado pela DigitalOcean). Você também pode adicionar tags para ajudar a localizar sua Droplet no futuro, caso venha a ter várias Droplets na sua conta.

Vale destacar, por último, a opção de backups. Um backup sempre adiciona 20% ao valor mensal de sua Droplet e com ele você tem a vantagem de ter um backup semanal automático do seu sistema. Muito útil para ambientes de produção, mas desnecessário nessa fase de desenvolvimento.

Vamos clicar em Create Droplet para finalizar. Isso pode levar alguns minutos.

Finalizado o processo, você estará numa tela semelhante a essa:

Droplet criada!

Agora você pode acessar sua droplet através do endereço de IP informado. Vamos abrir o terminal e executar o seguinte comando:

$ ssh root@ip-da-droplet

No meu caso, ficou assim:

$ ssh root@67.205.181.243

Se você escolheu autenticação por chave SSH você acessará sua Droplet imediatamente. Caso tenha escolhido autenticação via usuário/senha será pedido que você informe a senha que você recebeu via email, bem como será pedido que crie uma nova senha logo em seguida.

Recomendo que sigam esse tutorial da DigitalOcean para configuração inicial de um servidor.

No nosso caso, vamos seguir com o usuário root padrão mesmo, mas fica o alerta que isso não é recomendado em ambiente de produção. Estamos utilizando ele apenas para testes, em um ambiente de desenvolvimento.

Como estamos utilizando o docker, vamos instalá-lo na nossa droplet:

$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sh get-docker.sh
$ rm get-docker.sh

Em seguida, vamos instalar o docker-compose. Acesse o link do github para ver qual a release mais recente, bem como encontrar os comandos para instalação da mesma. No nosso caso, a release mais recente no instante em que escrevia esse tutorial era a 1.25.4. Então a instalação fica assim:

$ curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

Em seguida:

$ chmod +x /usr/local/bin/docker-compose

E então, para verificar se está funcionando:

$ docker-compose --version

A saída deve ser algo como:

$ docker-compose version 1.25.4, build 8d51620a

Detalhe: Já aconteceu comigo algumas vezes do comando simplesmente travar e não exibir nenhum resultado. Algumas vezes a memória de 1GB da Droplet padrão não é o suficiente para executar o comando. Para o ambiente de testes, vamos adicionar um arquivo de swap à nossa Droplet:

$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile

Por último, precisamos editar o arquivo /etc/fstab para que a alteração seja permanente:

$ sudo nano /etc/fstab

E adicionar ao final do arquivo:

/swapfile swap swap defaults 0 0

Pressione ctrl+o para salvar e ctrl+x para sair.

Execute o comando novamente:

$ docker-compose --version

E agora deverá receber a saída desejada.

Agora vamos às alterações que devem ser feitas no nosso projeto para prosseguirmos com o deploy no servidor.

Primeiro, vamos adicionar um Dockerfile para inicializar o container da nossa API, na raiz do nosso projeto (fora de src):

api.Dockerfile

Repassando o que o Dockerfile está especificando:

  1. Vamos partir da imagem node:alpine;
  2. Criamos um diretório em /usr/src chamado node-api;
  3. Definimos o diretório recém criado como nosso diretório atual;
  4. Instalamos possíveis atualizações do nosso sistema operacional, no caso o alpine;
  5. Instalamos o pyhton3, g++ e o make, que são necessários para o bom funcionamento do npm install;
  6. Copiamos o conteúdo do nosso diretório atual para o diretório recém criado dentro do container;
  7. Rodamos o npm install;
  8. Instalamos mais alguns pacotes, dessa vez o msmtp, equivalente ao sendmail para o alpine, necessário para enviarmos emails;
  9. Criamos um atalho para o msmtp com o nome de sendmail para que nossa aplicação o execute quando tentar executar o sendmail;
  10. Abrimos a porta 3000
  11. Rodamos o comando npm run start:dev para inicializar a API dentro do container.

Vamos criar também um arquivo .dockerignore no mesmo local:

.dockerignore

Esse arquivo especifica quais pastas/arquivos devem ser ignorados pelo comando COPY do Dockerfile.

Agora vamos adicionar o serviço da nossa API, especificado no Dockerfile, ao docker-compose.yml:

docker-compose.yml

Reparem que dessa vez, ao invés de especificarmos uma imagem do docker hub, especificamos para o docker-compose construir uma imagem utilizando o api.Dockerfile e utilizá-la para montar o container.

Por último, vamos alterar o arquivo src/configs/typeorm.config.ts:

typeorm.config.ts

Essa alteração foi bem pequena: alteramos o host do banco de dados de local host para pgsql, que é a forma como o container da API vai conseguir acessar o container do banco de dados. Vamos subir essas alterações para o Git (se você clonar o repositório da parte 7 do meu GitHub ele já virá com essas alterações, apenas especifiquei elas aqui para que entendam o que está acontecendo).

Vamos voltar ao nosso servidor e clonar o repositório da nossa aplicação:

$ git clone https://github.com/iagomaia/nestjs-medium-parte7
$ cd nestjs-medium-parte7

Agora vamos subir nossos containers:

$ docker-compose up

Essa será a saída ao finalizar:

API funcionando no servidor!

Alguns detalhes:

  1. Você poderá realizar requisições para o endereço IP da sua droplet, na porta 3000.
  2. Para prevenir o uso das Droplets como meio de envio de emails de spam a DigitalOcean bloqueia automaticamente as portas necessárias para o envio de emails por 60 dias após a criação da Droplet, então nossos serviços de envio de emails não irão funcionar.
  3. Você pode enviar emails normalmente se utilizar serviços como o Sendgrid ou o Mailgun.
  4. Você também pode solicitar via ticket o desbloqueio de sua Droplet, mas isso leva um certo tempo.
  5. Ao acessar o endereço de sua Droplet no navegador na porta 8080 você terá acesso ao Adminer para visualizar seu banco de dados.
Acessando Adminer no navegador

E com isso finalizamos nossa série de tutorial, espero que tenham gostado!

--

--