Posts
Configurando Integração Contínua no Ubuntu com Nodejs
15 de agosto de 2015 • 11 min de leitura
Passei por sangue, suor e lágrimas para trazer isso para você. Sofri o calor escaldante do Vale da Morte e subi os picos do Monte McKinley. Sacrifiquei muito.
Grande parte do conteúdo compartilhado neste post não é trabalho original meu. Quando posso, faço referência ao trabalho original.
Este artigo assume que você consegue se mover pelo Linux.
Não consegui encontrar um guia abrangente sobre hospedagem e gerenciamento de aplicações Nodejs no Ubuntu em capacidade de produção. Reuni múltiplos artigos sobre o assunto. Ao final deste artigo, espero que você consiga configurar seu próprio servidor Ubuntu e ter Nodejs implantando via um servidor de integração contínua.
Ambiente
Estou usando TeamCity no Windows que então implanta código do GitHub para Ubuntu hospedado na AWS.
Tecnologias
Para este artigo usei as seguintes tecnologias:
- Ubuntu 14.04 na AWS
- Plink 0.64
- TeamCity 9.1
- GitHub
- Nginx 1.9.3
Configurando Ubuntu
Não vou entrar em detalhes aqui. Amazon Web Services (AWS) torna isso bem fácil de fazer. Não importa onde está ou se está em seu próprio servidor.
Encontrei alguns problemas. Primeiro, certifique-se de que a porta 80 está aberta. Cometi o erro tolo de tentar conectar com a porta 80 fechada. Uma vez que descobri meu erro, me senti como a bunda de um rinoceronte.
Instalando Nodejs a partir da Fonte
Nodejs é uma tecnologia de servidor que usa o mecanismo javascript V8 do Google. Desde seu lançamento em 2010, tornou-se amplamente popular.
As instruções a seguir vieram originalmente de um post do Digital Ocean.
Você sempre tem a opção de instalar Nodejs a partir do apt-get, mas estará algumas versões atrás. Para obter os bits mais recentes, instale Nodejs a partir da fonte.
Ao final desta seção teremos baixado a versão estável mais recente do node (conforme este artigo), teremos compilado a fonte e instalado Nodejs.
Faça login em seu servidor. Começaremos atualizando as listas de pacotes.
sudo apt-get update
Também estou sugerindo que você atualize todos os pacotes. Isso não é necessário para Nodejs, mas é uma boa prática manter seu servidor atualizado.
sudo apt-get upgrade
Seu servidor está totalmente atualizado. É hora de baixar a fonte.
cd ~
No momento da escrita, 12.7 é a versão estável mais recente do Nodejs. Confira nodejs.org para a versão mais recente.
wget https://nodejs.org/dist/v0.12.7/node-v0.12.7.tar.gz
Extraia o arquivo que você baixou.
tar xvf node-v*
Mude para o diretório recém-criado
cd node-v*
Configure e compile Nodejs.
./configure
make
Instale Nodejs
sudo make install
Para remover os arquivos baixados e extraídos. Claro, isso é opcional.
cd ~
rm -rf node-v*
Parabéns! Nodejs agora está instalado! E não foi muito difícil.
Configurando Nginx
Nodejs pode atuar como um servidor web, mas não é o que eu gostaria de expor ao mundo. Um servidor web industrial, endurecido e rico em recursos é mais adequado para isso. Recorri ao Nginx para essa tarefa.
É um servidor web maduro com os recursos que precisamos. Para executar mais de uma instância do Nodejs, precisaremos de encaminhamento de porta.
Você pode estar pensando, por que precisamos de mais de uma instância do Nodejs executando ao mesmo tempo. Essa é uma pergunta justa… No meu cenário, tenho um servidor e preciso executar DEV, QA e PROD na mesma máquina. Sim, eu sei que não é ideal, mas não quero configurar 3 servidores para cada ambiente.
Para começar, vamos instalar Nginx
sudo -s
add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx
Uma vez que Nginx foi instalado com sucesso, precisamos configurar os domínios. Vou assumir que você desejará ter cada um de seus sites em seu próprio domínio/subdomínio. Se você não quiser e quiser usar diferentes subpastas, isso é possível e muito fácil de fazer. Não vou cobrir esse cenário aqui. Há toneladas de documentação sobre como fazer isso. Há muito pouca documentação sobre como configurar diferentes domínios e encaminhamento de porta para as instâncias Nodejs correspondentes. Isso é o que vou cobrir.
Agora que Nginx está instalado, crie um arquivo para yourdomain.com em /etc/nginx/sites-available/
sudo nano /etc/nginx/sites-available/yourdomain.com
Adicione a seguinte configuração ao seu arquivo recém-criado
# o(s) IP(s) em que seu servidor node está executando. Escolhi a porta 9001.
upstream app_myapp1 {
server 127.0.0.1:9001;
keepalive 8;
}
# a instância do servidor nginx
server {
listen 80;
server_name yourdomain.com;
access_log /var/log/nginx/yourdomain.log;
# passar a solicitação para o servidor node.js com os cabeçalhos corretos
# e muito mais pode ser adicionado, veja as opções de configuração do nginx
location / {
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://app_myapp1;
}
}
Certifique-se de substituir “yourdomain.com” pelo seu domínio real. Salve e saia do seu editor.
Crie um link simbólico para este arquivo no diretório sites-enabled.
cd /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/yourdomain.com yourdomain.com
Para testar se tudo está funcionando corretamente, crie um aplicativo node simples e salve-o em /var/www/yourdomain.com/app.js e execute-o.
Aqui está um aplicativo nodejs simples se você não tiver um à mão.
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');}).listen(9001, "127.0.0.1");
console.log('Server running at http://127.0.0.1:9001/');
Vamos reiniciar Nginx.
sudo /etc/init.d/nginx restart
Não se esqueça de iniciar sua instância Nodejs, se ainda não o fez.
cd /var/www/yourdomain/ && node app.js
Se tudo estiver funcionando corretamente, quando você navegar para yourdomain.com, verá “Hello World.”
Para adicionar outro domínio para uma instância Nodejs diferente, você precisa repetir as etapas acima. Especificamente, você precisará alterar o nome upstream, a porta e o domínio em seu novo arquivo de configuração Nginx. O endereço proxy_pass deve corresponder ao nome upstream no arquivo de configuração nginx. Observe o nome upstream e o valor proxy_pass e você verá o que quero dizer.
Para recapitular, instalamos NodeJS a partir da fonte e acabamos de terminar de instalar Nginx. Configuramos e testamos o encaminhamento de porta com Nginx e Nodejs
Instalando PM2
Você pode estar se perguntando “O que é PM2?” como fiz quando ouvi falar sobre. PM2 é um gerenciador de processos para aplicações Nodejs. Nodejs não vem com muito. Isso faz parte de seu apelo. A desvantagem disso é que você tem que fornecer as camadas na frente. PM2 é uma dessas camadas.
PM2 gerencia a vida do processo Nodejs. Quando é encerrado, PM2 o reinicia. Quando o servidor reinicia, PM2 reinicia todos os processos Nodejs para você. Ele também possui um extenso processo de ciclo de vida de desenvolvimento. Não vamos cobrir esse aspecto do PM2. Encorajo você a ler a documentação bem escrita.
Assumindo que você está conectado ao terminal, começaremos instalando PM2 via NPM. Npm é o gerenciador de pacotes Nodejs (npm). Foi instalado quando você instalou Nodejs.
sudo npm install pm2 -g
É isso. PM2 agora está instalado.
Usando PM2
PM2 é fácil de usar.
O hello world para PM2 é simples.
pm2 start hello.js
Isso adiciona seu aplicativo à lista de processos do PM2. Esta lista é exibida cada vez que um aplicativo é iniciado.

Neste exemplo, existem dois aplicativos Nodejs em execução. Um chamado api.dev e api.pre.
PM2 atribui automaticamente o nome do aplicativo ao “App name” na lista.
Fora da caixa, PM2 não se configura para iniciar quando o servidor reinicia. O comando é diferente para os diferentes sabores do Linux. Estou executando no Ubuntu, então vou executar o comando do Ubuntu.
pm2 start ubuntu
Ainda não terminamos. Temos que adicionar um caminho para o binário PM2. Felizmente, a saída do comando anterior nos diz como fazer isso.
Saída:
[PM2] You have to run this command as root
[PM2] Execute the following command :
[PM2] sudo env PATH=$PATH:/usr/local/bin pm2 startup ubuntu -u sammy
Execute o comando que foi gerado (semelhante à saída destacada acima) para configurar PM2 para iniciar na inicialização (use o comando de sua própria saída):
sudo env PATH=$PATH:/usr/local/bin pm2 startup ubuntu -u sammy
Exemplos de outros usos do PM2 (opcional)
Parando um aplicativo pelo nome do aplicativo
pm2 stop example
Reiniciando pelo nome do aplicativo
pm2 restart example
Lista de aplicativos atuais gerenciados pelo PM2
pm2 list
Especificando um nome ao iniciar um processo. Se você chamar, PM2 usa o arquivo javascript como o nome. Isso pode não funcionar para você. Aqui está como especificar o nome.
pm2 start www.js --name api.pre
Isso deve ser suficiente para você começar com PM2. Para saber mais sobre os recursos do PM2, visite o Repositório GitHub.
Configurando e Usando Plink
Você provavelmente está pensando, “O que em nome da vaca de Betsey é Plink?” Pelo menos é o que pensei. Ainda não tenho certeza o que pensar sobre isso. Nunca vi nada assim.
Você já assistiu ao filme Wall-e? Wall-e tira uma colher de garfo. Primeiro ele tenta colocá-la com os garfos, mas não encaixa e depois tenta colocá-la com as colheres, mas não encaixa. Bem, isso é Plink. É um cruzamento entre Putty (SSH) e a Linha de Comando do Windows.
Plink basicamente permite que você execute comandos bash através da linha de comando do Windows enquanto conectado a um shell Linux (e provavelmente Unix).
Comece baixando Plink. É apenas um executável. Recomendo colocá-lo em C:/Program Files (x86)/Plink. Precisaremos fazer referência a ele mais tarde.
Se você estiver executando uma instância Ubuntu na AWS. Você já terá um certificado configurado para Putty (estou assumindo que você está usando Putty).
Se não estiver, você precisará garantir que tenha um certificado ssh compatível para Ubuntu na AWS.
Se você não estiver usando AWS, pode especificar o nome de usuário e senha na linha de comando e não precisará se preocupar com os certificados ssh.
Aqui está um exemplo de comando de linha que se conecta ao Ubuntu com Plink.
"C:\Program Files (x86)\Plink\plink.exe" -ssh ubuntu@xx.xx.xx.xx -i "C:\Program Files (x86)\Plink\ssh certs\aws-ubuntu.ppk"

Isso pode estar nos adiantando, mas para executar um script ssh no servidor Ubuntu, adicionamos o caminho completo ao final do comando Plink.
"C:\Program Files (x86)\Plink\plink.exe" -ssh ubuntu@xx.xx.xx.xx -i "C:\Program Files (x86)\Plink\ssh certs\aws-ubuntu.ppk" /var/www/deploy-dev-ui.sh
E isso, caro leitor, é Plink.
Entendendo NODE_ENV
NODE_ENV é uma variável de ambiente popularizada pelo expressjs. Antes de iniciar a instância do node, defina o NODE_ENV para o ambiente. No código, você pode carregar arquivos específicos com base no ambiente.
Configurando NODE_ENV
Linux & Mac: export NODE_ENV=PROD
Windows: set NODE_ENV=PROD
A variável de ambiente é recuperada dentro de uma instância Nodejs usando process.env.NODE_ENV.
exemplo
var environment = process.env.NODE_ENV
ou com expressjs
app.get('env')
*Nota: app.get('env') padrão é “development”.
Juntando tudo
Nodejs, PM2, Nginx e Plink estão instalados e esperançosamente funcionando. Agora precisamos juntar todas essas peças em uma solução de integração contínua.
Clone seu repositório GitHub em /var/www/yourdomain.com. Embora SSH seja mais seguro que HTTPS, recomendo usar HTTPS. Sei que isso não é ideal, mas não consegui fazer Plink funcionar com GitHub no Ubuntu. Sem entrar em muitos detalhes, Plink e os formatos de certificado SSH do GitHub são diferentes e chamar GitHub via Plink através de SSH não funcionou. Se você conseguir descobrir o problema, me avise!
Para fazer o pull do GitHub sem intervenção, o nome de usuário e a senha precisarão fazer parte da URL de origem.
Aqui está como você define sua URL de origem. Claro, você precisará substituir suas informações onde apropriado.
git remote set-url origin https://username:password@github.com/username/yourdomain.git
Clone seu repositório.
cd /var/www/yourdomain.com
git clone https://username:password@github.com/username/yourdomain.git .
Observe que, se este diretório não estiver completamente vazio, incluindo arquivos ocultos, Git não clonará o repositório para este diretório.
Para encontrar arquivos ocultos no diretório, execute este comando
ls -a
Para a cola, estamos usando um script de shell. Aqui está uma cópia do meu script.
#!/bin/bash
echo "> Current PM2 Apps"
pm2 list
echo "> Stopping running API"
pm2 stop api.dev
echo "> Set Environment variable."
export NODE_ENV=DEV
echo "> Changing directory to dev.momentz.com."
cd /var/www/yourdomain.com
echo "> Listing the contents of the directory."
ls -a
echo "> Remove untracked directories in addition to untracked files."
git clean -f -d
echo "> Pull updates from Github."
git pull
echo "> Install npm updates."
sudo npm install
echo "> Transpile the ECMAScript 2015 code"
gulp babel
echo "> Restart the API"
pm2 start transpiled/www.js --name api.dev
echo "> List folder directories"
ls -a
echo "> All done."
Lanço este script de shell com TeamCity, mas você pode lançar com qualquer coisa.
Aqui está o comando bruto.
"C:\Program Files (x86)\Plink\plink.exe" -ssh ubuntu@xx.xx.xx.xx -i "C:\Program Files (x86)\Plink\ssh certs\aws-ubuntu.ppk" /var/www/deploy-yourdomain.sh
exit
>&2
É isso.
Fechando
Este processo tem algumas arestas ásperas… Espero polir essas arestas com o tempo. Se você tiver sugestões, deixe-as nos comentários.
Este documento está em meu Repositório GitHub. As tecnologias mudam, então se você encontrar um erro, atualize-o. Então vou atualizar este post.
Autor: Chuck Conway é um Engenheiro de IA com quase 30 anos de experiência em engenharia de software. Ele constrói sistemas de IA práticos—pipelines de conteúdo, agentes de infraestrutura e ferramentas que resolvem problemas reais—e compartilha o que está aprendendo ao longo do caminho. Conecte-se com ele nas redes sociais: X (@chuckconway) ou visite-o no YouTube e no SubStack.