Tutorial

Como configurar um aplicativo Node.js para produção no Ubuntu 20.04

NginxNode.jsApplications

Introdução

O Node.js é um ambiente de execução de código aberto do JavaScript para construção de aplicativos de rede e do servidor. A plataforma executa nos sistemas operacionais Linux, macOS, FreeBSD e Windows. Embora você possa executar aplicativos Node.js na linha de comando, este tutorial se concentrará em executá-los como um serviço. Isso significa que eles irão reiniciar após reinicialização ou falha, sendo seguros para utilização em um ambiente de produção.

Neste tutorial, você irá configurar um ambiente Node.js pronto para produção em um único servidor Ubuntu 20.04. Este servidor executará um aplicativo Node.js gerenciado pelo PM2 e fornecerá aos usuários acesso seguro ao aplicativo através de um proxy reverso Nginx. O servidor Nginx oferecerá HTTPS usando um certificado gratuito fornecido pelo Let’s Encrypt.

Pré-requisitos

Este guia supõe que você tenha o seguinte:

Quando você tiver cumprido com os pré-requisitos, você terá um servidor atendendo a página do espaço reservado padrão do seu domínio em https://example.com/.

Passo 1 — Instalando o Node.js

Vamos começar instalando a versão mais recente do Node.js com LTS, ou Long-Term Support (Suporte de longo prazo), usando os arquivos do pacote NodeSource.

Primeiramente, instale o NodeSource PPA para ter acesso ao seu conteúdo. Certifique-se de que você esteja em seu diretório base, e use o curl para recuperar o script de instalação para a versão LTS mais recente do Node.js dos seus arquivos.

  • cd ~
  • curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh

É possível verificar o conteúdo deste script com o nano ou seu editor de texto preferido:

  • nano nodesource_setup.sh

Quando terminar de inspecionar o script, execute-o sob o sudo:

  • sudo bash nodesource_setup.sh

O PPA será adicionado à sua configuração e seu cache de pacotes local será atualizado automaticamente. Após executar o script de configuração do Nodesource, você pode instalar o pacote do Node.js:

  • sudo apt install nodejs

Para verificar qual versão do Node.js você tem instalada após esses passos iniciais, digite:

  • nodejs -v
Output
v14.4.0

Nota: ao instalar a partir do NodeSource com PPA, o arquivo executável Node.js é chamado de nodejs e não node.

O pacote nodejs contém o binário do nodejs assim como o npm, um gerenciador de pacotes para módulos Node, então não é necessário instalar o npm separadamente.

O npm usa um arquivo de configuração no seu diretório home para controlar as atualizações. Ele será criado na primeira vez que você executar o npm. Execute este comando para verificar se o npm está instalado e crie o arquivo de configuração:

  • npm -v
Output
6.14.5

Para que alguns pacotes npm possam funcionar (os que requerem compilar o código da fonte, por exemplo), será necessário instalar o pacote build-essential:

  • sudo apt install build-essential

Agora, você tem as ferramentas necessárias para trabalhar com os pacotes npm que requerem a compilação do código da fonte.

Com o ambiente de execução Node.js instalado, vamos seguir em frente para escrever um aplicativo Node.js.

Passo 2 — Criando um aplicativo Node.js

Vamos escrever um aplicativo Hello World que retorna “Hello World” a qualquer pedido de HTTP. Este aplicativo exemplo ajudará você a configurar o Node.js. Você pode substituí-lo pelo seu próprio aplicativo — certifique-se apenas de que você modifique seu aplicativo para escutar os endereços IP e portas apropriadas.

Primeiramente, vamos criar um aplicativo exemplo chamado hello.js:

  • cd ~
  • nano hello.js

Insira o seguinte código no arquivo:

~/hello.js
const http = require('http');

const hostname = 'localhost';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World!\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Salve o arquivo e saia do editor.

Este aplicativo Node.js escuta no endereço especificado (localhost) e porta (3000) e retorna “Hello World!” com um código de sucesso HTTP 200. Uma vez que estamos escutando no localhost, clientes remotos não poderão se conectar ao nosso aplicativo.

Para testar seu aplicativo, digite:

  • node hello.js

Você receberá o seguinte resultado:

Output
Server running at http://localhost:3000/

Nota: executar um aplicativo Node.js dessa maneira irá bloquear comandos adicionais até que o aplicativo seja encerrado pressionando-se CTRL+C.

Para testar o aplicativo, abra outra sessão de terminal no seu servidor e conecte-se ao localhost com o curl:

  • curl http://localhost:3000

Caso obtenha o seguinte resultado, o aplicativo está funcionando corretamente e escutando no endereço e porta corretos:

Output
Hello World!

Caso não obtenha o resultado esperado, certifique-se de que seu aplicativo Node.js esteja funcionando e configurado para escutar no endereço e porta apropriados.

Assim que tiver certeza certeza de que ele está funcionando, encerre o aplicativo (se você ainda não o tiver feito) pressionando CTRL+C.

Passo 3 — Instalando o PM2

Em seguida, vamos instalar o PM2, um gerenciador de processos para aplicativos Node.js. O PM2 torna possível forçar os aplicativos a executarem como daemon para que eles executem em segundo plano como um serviço.

Utilize o npm para instalar a última versão do PM2 no seu servidor:

  • sudo npm install pm2@latest -g

A opção -g faz com que o npm instale o módulo globally, para que ele esteja disponível em todo o sistema.

Vamos usar primeiro o comando pm2 start para executar seu aplicativo, hello.js, em segundo plano:

  • pm2 start hello.js

Isso também adiciona seu aplicativo na lista de processos do PM2, que é produzida toda vez que você inicia um aplicativo:

Output
... [PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2 [PM2] PM2 Successfully daemonized [PM2] Starting /home/sammy/hello.js in fork_mode (1 instance) [PM2] Done. ┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐ │ id │ name │ mode │ ↺ │ status │ cpu │ memory │ ├────┼────────────────────┼──────────┼──────┼───────────┼──────────┼──────────┤ │ 0 │ hello │ fork │ 0 │ online │ 0% │ 25.2mb │ └────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

Assim como indicado acima, o PM2 atribui automaticamente um App name (baseado no nome do arquivo, sem a extensão .js) e um id do PM2. O PM2 também mantém outras informações, como o PID do processo, seu status atual e o uso de memória.

Os aplicativos que estão funcionando sob o PM2 serão reiniciados automaticamente se o aplicativo falhar ou for encerrado, mas podemos ir um passo além para fazer o aplicativo iniciar na inicialização do sistema usando o subcomando startup. Este subcomando gera e configura um script de inicialização para iniciar o PM2 e seus processos gerenciados nas inicializações do servidor:

  • pm2 startup systemd

A última linha da saída resultante incluirá um comando para ser executado com privilégios de superusuário para definir o PM2 para iniciar na inicialização:

Output
[PM2] Init System found: systemd sammy [PM2] To setup the Startup Script, copy/paste the following command: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Execute o comando a partir do resultado, com o seu nome de usuário no lugar de sammy:

  • sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sammy --hp /home/sammy

Como um passo adicional, podemos salvar a lista de processos PM2 e os ambientes correspondentes:

  • pm2 save

Agora, você criou uma unidade systemd que executa o pm2 para seu usuário na inicialização. Esta instância pm2, por sua vez, executa o hello.js.

Inicie o serviço com systemctl:

  • sudo systemctl start pm2-sammy

Se neste ponto você encontrar um erro, pode ser necessário reinicializar o sistema. Isso pode ser feito com o sudo reboot.

Verifique o status da unidade systemd:

  • systemctl status pm2-sammy

Para um panorama detalhado do systemd, veja Systemd Essentials: Working with Services, Units, and the Journal.

Além daqueles que abordamos, o PM2 fornece muitos subcomandos que permitem que você gerencie ou procure informações sobre seus aplicativos.

Interrompa um aplicativo com este comando (especifique o App name do PM2 ou id):

  • pm2 stop app_name_or_id

Reinicie um aplicativo:

  • pm2 restart app_name_or_id

Liste os aplicativos atualmente gerenciados pelo PM2:

  • pm2 list

Obtenha informações sobre um aplicativo específico usando seu App name:

  • pm2 info app_name

O monitor de processos do PM2 pode ser trazido com o subcomando monit. Isso mostra o status do aplicativo, da CPU, e o uso de memória:

  • pm2 monit

Note que executar o pm2 sem qualquer argumento também exibirá uma página de ajuda com exemplos de uso.

Agora que seu aplicativo Node.js está funcionando e é gerenciado pelo PM2, vamos configurar o proxy reverso.

Passo 4 — Configurando o Nginx como um Servidor de Proxy Reverso

Seu aplicativo está funcionando e escutando no localhost, mas você precisa configurar uma forma dos seus usuários acesssarem ele. Vamos configurar o servidor Web Nginx como um proxy reverso com esse intuito.

Nos pré-requisitos do tutorial, você definiu sua configuração do Nginx no arquivo /etc/nginx/sites-available/example.com. Abra este arquivo para edição:

  • sudo nano /etc/nginx/sites-available/example.com

Dentro do bloco server, você deve ter um bloco location / existente. Substitua o conteúdo desse bloco com a seguinte configuração. Se seu aplicativo for configurado para escutar em uma porta diferente, atualize a parte em destaque com o número de porta correto:

/etc/nginx/sites-available/example.com
server {
...
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Isso configura o servidor para responder a pedidos em sua raiz. Supondo que nosso servidor esteja disponível em example.com, acessar o https://example.com/ através de um navegador Web enviaria o pedido para hello.js, escutando na porta 3000 do localhost.

Você pode adicionar blocos location adicionais ao mesmo bloco de servidor para fornecer acesso a outros aplicativos no mesmo servidor. Por exemplo, se você também estivesse executando outro aplicativo Node.js na porta 3001, você poderia adicionar este bloco de localização para permitir o acesso a ele através de https://example.com/app2:

/etc/nginx/sites-available/example.com — Optional
server {
...
    location /app2 {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
...
}

Assim que terminar de adicionar os blocos de localização para seus aplicativos, salve o arquivo e saia do seu editor.

Certifique-se de que não tenha introduzido qualquer erro de sintaxe digitando:

  • sudo nginx -t

Reinicie o Nginx:

  • sudo systemctl restart nginx

Supondo que o seu aplicativo Node.js esteja funcionando e o seu aplicativo e as configurações do Nginx estejam corretos, agora você deverá poder acessar seu aplicativo via proxy reverso do Nginx. Teste acessando o URL do seu servidor (seu endereço IP público ou nome de domínio).

Conclusão

Parabéns! Agora, você tem seu aplicativo Node.js funcionando atrás de um proxy reverso Nginx em um servidor Ubuntu 20.04. Esta configuração de proxy reverso é suficientemente flexível para fornecer o acesso aos seus usuários a outros aplicativos ou conteúdos Web estáticos que você queira compartilhar.

Creative Commons License