O autor selecionou a Fundação Electronic Frontier para receber uma doação como parte do programa Write for DOnations.
O Shipit é uma ferramenta de automação e implantação universal para desenvolvedores do Node.js. Ela possui um fluxo de tarefas baseado no pacote popular Orchestrator, comandos de login e SSH interativo através do OpenSSH, além de uma API extensível. Os desenvolvimentos podem usar o Shipit para automatizar os fluxos de trabalho de compilação e DE implantação para uma ampla gama de aplicativos Node.js.
O fluxo de trabalho do Shipit permite que os desenvolvedores não apenas configurem tarefas, mas também especifiquem a ordem na qual são executadas; se devem ser executadas de maneira sincronizada ou não e em qual ambiente.
Neste tutorial, você instalará e configurará o Shipit para implantar um aplicativo Node.js a partir do seu ambiente de desenvolvimento local para o seu ambiente de produção. Você usará o Shipit para implantar seu aplicativo e configurar o servidor remoto desta forma:
rsync
, git
e ssh
).Antes de iniciar este tutorial, você precisará do seguinte:
rsync
e git
instalados.
git
nas distribuições Linux, siga o tutorial Como instalar o Git.git
hospedados. Este tutorial usará o GitHub.Nota: os usuários do Windows terão que instalar o Subsistema Windows para o Linux para executar os comandos neste guia.
O Shipit exige um repositório Git para a sincronização entre a máquina de desenvolvimento local e o servidor remoto. Neste passo, você criará um repositório remoto no Github.com
. Embora cada provedor seja ligeiramente diferente, os comandos são de certo modo transferíveis.
Para criar um repositório, abra o Github.com
em seu navegador Web e faça login. Você notará que, no canto superior de todas as páginas, existe um símbolo de adição +. Clique no + e, em seguida, clique em Novo repositório.
Digite um nome curto e fácil de lembrar para o seu repositório como ,por exemplo, hello-world
. Note que, independentemente do nome que escolher aqui, ele será replicado como a pasta do projeto a partir da qual você irá trabalhar em sua máquina local.
De maneira opcional, adicione uma descrição do seu repositório.
Defina a visibilidade do seu repositório de acordo com sua preferência, como sendo pública ou privada.
Certifique-se de que o repositório seja inicializado com um .gitignore
, selecionando Node
na lista suspensa Add .gitignore
. Este passo é importante para evitar que arquivos desnecessários (como a pasta node_modules
) sejam adicionados ao seu repositório.
Clique no botão Criar repositório.
Agora, o repositório precisa ser clonado do Github.com
para sua máquina local.
Abra seu terminal e navegue até o local onde quer armazenar todos os seus arquivos do projeto Node.js. Note que este processo criará uma subpasta dentro do diretório atual. Para clonar o repositório para sua máquina local, execute o seguinte comando:
- git clone https://github.com/your-github-username/your-github-repository-name.git
Você precisará substituir o your-github-username
e your-github-repository-name
para que reflitam seu nome de usuário do Github e o nome do repositório anteriormente fornecido.
Nota: caso tenha habilitado a autenticação de dois fatores (2FA) no Github.com
, ao acessar o Github na linha de comando, você deverá usar um token de acesso pessoal ou uma chave SSH, em vez de sua senha. A página de ajuda do Github relacionada à 2FA fornece mais informações.
Você verá um resultado parecido com este:
OutputCloning into 'your-github-repository-name'...
remote: Enumerating objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Unpacking objects: 100% (3/3), done.
Vá até o repositório, executando o seguinte comando:
- cd your-github-repository-name
Dentro do repositório, há um arquivo e uma pasta únicos, sendo ambos arquivos usados pelo Git para gerenciar o repositório. Você pode verificar isso com:
- ls -la
Você verá um resultado parecido com este:
Outputtotal 8
0 drwxr-xr-x 4 asciant staff 128 22 Apr 07:16 .
0 drwxr-xr-x 5 asciant staff 160 22 Apr 07:16 ..
0 drwxr-xr-x 13 asciant staff 416 22 Apr 07:16 .git
8 -rw-r--r-- 1 asciant staff 914 22 Apr 07:16 .gitignore
Agora que você configurou um repositório git
funcional, irá criar o arquivo shipit.js
que gerencia o seu processo de implantação.
Neste passo, você criará um projeto Node.js como exemplo e, depois, adicionará os pacotes do Shipit. Este tutorial fornece um app exemplo — o servidor web Node.js que aceita solicitações HTTP e responde com um Hello World
em texto simples. Para criar o aplicativo, execute o seguinte comando:
- nano hello.js
Adicione o seguinte código de aplicativo exemplo ao hello.js
(atualizando a variável APP_PRIVATE_IP_ADDRESS
com o endereço IP da rede privada do servidor do seu app):
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8080, 'APP_PRIVATE_IP_ADDRESS');
console.log('Server running at http://APP_PRIVATE_IP_ADDRESS:8080/');
Agora, crie seu arquivo package.json
para seu aplicativo:
- npm init -y
Esse comando cria um arquivo package.json
, que você usará para configurar seu aplicativo Node.js. No próximo passo, você adicionará dependências a esse arquivo com a interface de linha de comando npm
.
OutputWrote to ~/hello-world/package.json:
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Em seguida, instale os pacotes npm
necessários com o seguinte comando:
- npm install --save-dev shipit-cli shipit-deploy shipit-shared
Aqui, você usará o sinalizador --save-dev
, uma vez que os pacotes do Shipit somente são necessários em sua máquina local. Você verá um resultado parecido com este:
Output+ shipit-shared@4.4.2
+ shipit-cli@4.2.0
+ shipit-deploy@4.1.4
updated 4 packages and audited 21356 packages in 11.671s
found 62 low severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details
Isso também adicionou os três pacotes ao seu arquivo package.json
como dependências de desenvolvimento:
. . .
"devDependencies": {
"shipit-cli": "^4.2.0",
"shipit-deploy": "^4.1.4",
"shipit-shared": "^4.4.2"
},
. . .
Com seu ambiente local configurado, agora você pode prosseguir com a preparação do servidor app remoto para implantações baseadas no Shipit.
Neste passo, você usará o ssh
para se conectar ao seu servidor app e instalar sua dependência remota rsync
. O Rsync é um utilitário para transferir e sincronizar arquivos de modo eficiente entre os discos do computador local e os computadores em rede, comparando os tempos de modificação e os tamanhos dos arquivos.
O Shipit usa o rsync
para transferir e sincronizar arquivos entre seu computador local e o servidor app remoto. Você não emitirá qualquer comando diretamente no rsync
; o Shipit fará isso por você.
Nota: o tutorial Como configurar um aplicativo Node.js para produção no CentOS 7 possibilitou que você ficasse com dois servidores, app e web. Esses comandos devem ser executados apenas no app.
Conecte-se ao seu servidor app remoto via ssh
:
- ssh deployer@your_app_server_ip
Instale o rsync
no seu servidor, executando o seguinte comando:
- sudo yum install rsync
Confirme a instalação com:
- rsync --version
Você verá uma linha semelhante no resultado deste comando:
Outputrsync version 3.1.2 protocol version 31
. . .
Você pode encerrar sua sessão ssh
, digitando exit
.
Com o rsync
instalado e disponível na linha de comando, você pode prosseguir com as tarefas de implantação e sua relação com eventos.
Tanto events quanto tasks são componentes chave das implantações Shipit. É importante entender como eles complementam a implantação do seu aplicativo. Os eventos desencadeados pelo Shipit representam pontos específicos no ciclo de vida da implantação. Suas tarefas executarão em reposta a esses eventos, com base na sequência do clico de vida do Shipit.
Um exemplo comum de onde esse sistema de tarefa/evento é útil em um aplicativo Node.js é na instalação das dependências do app (node_modules
), no servidor remoto. Mais adiante neste passo, você fará o Shipit escutar para o evento updated
(que é emitido depois que os arquivos do aplicativo são transferidos) e executar uma tarefa para instalar as dependências do aplicativo (npm install
) no servidor remoto.
Para escutar eventos e executar tarefas, o Shipit precisa de um arquivo de configuração que possua informações sobre seu servidor remoto (o servidor app) e registre ouvintes de eventos e os comandos a serem executados por essas tarefas. Esse arquivo fica no seu computador de desenvolvimento local, no diretório do seu aplicativo Node.js.
Para começar, crie esse arquivo, incluindo informações sobre seu servidor remoto, os ouvintes de eventos nos quais quer se inscrever e algumas definições das suas tarefas. Crie o shipitfile.js
no diretório raiz do seu aplicativo, em sua máquina local, executando o seguinte comando:
- nano shipitfile.js
Agora que você criou um arquivo, ele precisa ser preenchido com as informações iniciais do ambiente que o Shipit precisa. Basicamente, esse é o local do seu repositório Git
remoto e, mais importante que tudo, do endereço IP público e da conta de usuário SSH do seu servidor app.
Adicione essa configuração inicial e atualize as linhas destacadas para que correspondam ao seu ambiente:
module.exports = shipit => {
require('shipit-deploy')(shipit);
require('shipit-shared')(shipit);
const appName = 'hello';
shipit.initConfig({
default: {
deployTo: '/home/sammy/your-domain',
repositoryUrl: 'https://git-provider.tld/YOUR_GIT_USERNAME/YOUR_GIT_REPO_NAME.git',
keepReleases: 5,
shared: {
overwrite: true,
dirs: ['node_modules']
}
},
production: {
servers: 'sammy@YOUR_APP_SERVER_PUBLIC_IP'
}
});
const path = require('path');
const ecosystemFilePath = path.join(
shipit.config.deployTo,
'shared',
'ecosystem.config.js'
);
// Our listeners and tasks will go here
};
Atualizando as variables no seu método shipit.initConfig
dá ao Shipit uma configuração específica para sua implantação. Essas variáveis representam o seguinte para o Shipit:
deployTo:
é o diretório onde o Shipit implantará o código do seu aplicativo no servidor remoto. Aqui, você usa a pasta /home/
para um usuário não raiz com privilégios sudo
(/home/sammy
) uma vez que é segura e evitará problemas de permissão. O componente /your-domain
é uma convenção de nomenclatura para distinguir a pasta das demais na pasta inicial do usuário.repositoryUrl:
é a URL do repositório completo do Git. O Shipit usará essa URL para garantir que os arquivos do projeto estejam em sincronia antes da implantação.keepReleases:
é o número de lançamentos a ser mantido no servidor remoto. Um release
(lançamento) é uma pasta com data que contém os arquivos do seu aplicativo no momento do lançamento. Eles podem ser úteis para rollback
(reverter) uma implantação.shared:
é a configuração que corresponde aos keepReleases
que permite que os diretórios sejam shared
(compartilhados) entre os lançamentos. Nessa instância, temos uma única pasta node_modules
, que é compartilhada entre todos os lançamentos.production:
representa um servidor remoto para o qual implantar seu aplicativo. Nessa instância, você tem um servidor (servidor app) único, ao qual você dá o nome de production
, com o servers:
configuração que correspondendo ao seu user
SSH e ao public ip address
do SSH. O nome production
corresponde ao comando de implantação do Shipit usado ao final deste tutorial (npx shipit server name deploy
ou, no seu caso, npx shipit production deploy
).No repositório Github para o Shipit, você pode encontrar mais informações sobre a o objeto de Configuração da implantação do Shipit.
Antes de continuar a atualizar seu shipitfile.js
, vamos analisar o seguinte exemplo de trecho de código para entender as tarefas do Shipit:
Example event listenershipit.on('deploy', () => {
shipit.start('say-hello');
});
shipit.blTask('say-hello', async () => {
shipit.local('echo "hello from your local computer"')
});
Esse é um exemplo de tarefa que utiliza o método shipit.on
para se inscrever no evento deploy
(implantar). Essa tarefa esperará que o evento deploy
seja emitido pelo ciclo de vida do Shipit. Depois, quando o evento é recebido, a tarefa executa o método shipit.start
, que diz ao Shipit para start
(iniciar) a tarefa say-hello
.
O método shipit.on
aceita dois parâmetros, o nome do evento para escutar e a função de callback a ser executada quando o evento for recebido.
Sob a declaração do método shipit.on
, a tarefa é definida com o método shipit.blTask
. Isso cria uma tarefa do Shipit que irá bloquear outras tarefas durante sua execução (é uma tarefa síncrona). O método shipit.blTask
também aceita dois parâmetros, o nome da tarefa que está definindo e uma função de callback para ser executada quando a tarefa for ativada pelo shipit.start
.
Dentro da função de callback dessa tarefa exemplo (say-hello
), o método shipit.local
executa um comando na máquina local. O comando local ecoa "hello from your local computer"
no resultado do terminal.
Se quisesse executar um comando no servidor remoto, usaria o método shipit.remote
. Os dois métodos, shipit.local
e shipit.remote
, fornecem uma API para emitir comandos tanto localmente quanto remotamente como parte de uma implantação.
Agora, atualize o shipitfile.js
para incluir ouvintes de eventos para se inscrever no ciclo de vida do Shipit com shipit.on
. Adicione os ouvintes de eventos ao seu shipitfile.js
, inserindo-os após o espaço reservado para comentário da configuração inicial // Our tasks will go here
:
. . .
shipit.on('updated', () => {
shipit.start('npm-install', 'copy-config');
});
shipit.on('published', () => {
shipit.start('pm2-server');
});
Esses dois métodos estão escutando os eventos updated
e published
que são emitidos como parte do ciclo de vida da implantação do Shipit. Quando os eventos forem recebidos, cada qual irá iniciar tarefas usando o método shipit.start
, assim como na tarefa exemplo.
Agora que você agendou os ouvintes, adicionará a tarefa correspondente. Adicione a seguinte tarefa ao seu shipitfile.js
, inserindo-a após seus ouvintes de eventos:
. . .
shipit.blTask('copy-config', async () => {
const fs = require('fs');
const ecosystem = `
module.exports = {
apps: [
{
name: '${appName}',
script: '${shipit.releasePath}/hello.js',
watch: true,
autorestart: true,
restart_delay: 1000,
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}
]
};`;
fs.writeFileSync('ecosystem.config.js', ecosystem, function(err) {
if (err) throw err;
console.log('File created successfully.');
});
await shipit.copyToRemote('ecosystem.config.js', ecosystemFilePath);
});
Primeiro, você declara uma tarefa chamada copy-config
. Essa tarefa cria um arquivo local chamado ecosystem.config.js
e, depois, copia esse arquivo para o seu servidor remoto app. O PM2
usa esse arquivo para gerenciar seu aplicativo Node.js. Ela fornece as informações necessárias do caminho do arquivo para o PM2
para garantir que ele esteja executando seus arquivos mais recentemente implantados. Mais adiante no processo de compilação, você criará uma tarefa que executa o PM2
com o ecosystem.config.js
como configuração.
Caso seu aplicativo precise de variáveis de ambiente (como uma string de conexão com banco de dados), você pode declará-las tanto localmente em env:
quanto no servidor remoto em env_production:
da mesma maneira que você definiu a variável NODE_ENV
nesses objetos.
Adicione a próxima tarefa ao seu shipitfile.js
após a tarefa copy-config
:
. . .
shipit.blTask('npm-install', async () => {
shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
});
Em seguida, declare uma tarefa chamada npm-install
. Essa tarefa usa um terminal bash remoto (via shipit.remote
) para instalar as dependências do app (pacotes npm
).
Adicione a última tarefa ao seu shipitfile.js
depois da tarefa npm-install
:
. . .
shipit.blTask('pm2-server', async () => {
await shipit.remote(`pm2 delete -s ${appName} || :`);
await shipit.remote(
`pm2 start ${ecosystemFilePath} --env production --watch true`
);
});
Por fim, declare uma tarefa chamada pm2-server
. Essa tarefa também usa um terminal bash remoto para primeiro impedir o PM2
de gerenciar sua implantação anterior pelo comando delete
e, em seguida, iniciar uma nova instância do seu servidor Node.js, fornecendo o arquivo ecosystem.config.js
como uma variável. Além disso, você também avisa o PM2
que ele deve usar variáveis de ambiente a partir do bloco production
na sua configuração inicial e pede ao PM2
para monitorar o aplicativo, reiniciando-o caso falhe.
O arquivo completo do shipitfile.js
:
module.exports = shipit => {
require('shipit-deploy')(shipit);
require('shipit-shared')(shipit);
const appName = 'hello';
shipit.initConfig({
default: {
deployTo: '/home/deployer/example.com',
repositoryUrl: 'https://git-provider.tld/YOUR_GIT_USERNAME/YOUR_GIT_REPO_NAME.git',
keepReleases: 5,
shared: {
overwrite: true,
dirs: ['node_modules']
}
},
production: {
servers: 'deployer@YOUR_APP_SERVER_PUBLIC_IP'
}
});
const path = require('path');
const ecosystemFilePath = path.join(
shipit.config.deployTo,
'shared',
'ecosystem.config.js'
);
// Our listeners and tasks will go here
shipit.on('updated', async () => {
shipit.start('npm-install', 'copy-config');
});
shipit.on('published', async () => {
shipit.start('pm2-server');
});
shipit.blTask('copy-config', async () => {
const fs = require('fs');
const ecosystem = `
module.exports = {
apps: [
{
name: '${appName}',
script: '${shipit.releasePath}/hello.js',
watch: true,
autorestart: true,
restart_delay: 1000,
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}
]
};`;
fs.writeFileSync('ecosystem.config.js', ecosystem, function(err) {
if (err) throw err;
console.log('File created successfully.');
});
await shipit.copyToRemote('ecosystem.config.js', ecosystemFilePath);
});
shipit.blTask('npm-install', async () => {
shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
});
shipit.blTask('pm2-server', async () => {
await shipit.remote(`pm2 delete -s ${appName} || :`);
await shipit.remote(
`pm2 start ${ecosystemFilePath} --env production --watch true`
);
});
};
Salve e saia do arquivo quando estiver pronto.
Com seu shipitfile.js
configurado, ouvintes de eventos e as tarefas finalizadas associadas, você pode prosseguir com a implantação para o servidor app.
Neste passo, você implantará seu aplicativo remotamente e testará se a implantação disponibilizou seu aplicativo na internet.
Como o Shipit clona os arquivos do projeto do repositório remoto do Git, você precisa mandar seus arquivos do aplicativo local Node.js da sua máquina local para o Github. Navegue até o diretório do seu aplicativo do projeto Node.js (onde seu hello.js
e shipitfile.js
estão localizados) e execute o seguinte comando:
- git status
O comando git status
mostra o estado do diretório de trabalho e a área de preparação. Ele permite que você veja quais alterações foram preparadas, quais não foram e quais arquivos o Git não está rastreando. Seus arquivos não estão rastreados e aparecem em vermelho no resultado:
OutputOn branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.js
package-lock.json
package.json
shipitfile.js
nothing added to commit but untracked files present (use "git add" to track)
Você pode adicionar esses arquivos ao seu repositório com o seguinte comando:
- git add --all
Esse comando não gera nenhum resultado, embora caso fosse executar o git status
novamente, os arquivos apareceriam em verde, com uma nota avisando que existem alterações a serem confirmadas.
Você pode criar uma confirmação, executando o seguinte comando:
- git commit -m "Our first commit"
O resultado desse comando fornece algumas informações específicas do Git sobre os arquivos.
Output[master c64ea03] Our first commit
4 files changed, 1948 insertions(+)
create mode 100644 hello.js
create mode 100644 package-lock.json
create mode 100644 package.json
create mode 100644 shipitfile.js
Agora, tudo o que resta é mandar sua confirmação para o repositório remoto, para que o Shipit clonar para o seu servidor app durante a implantação. Execute o seguinte comando:
- git push origin master
O resultado inclui informações sobre a sincronização com o repositório remoto:
OutputEnumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 8 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 15.27 KiB | 7.64 MiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:Asciant/hello-world.git
e274312..c64ea03 master -> master
Para implantar seu aplicativo, execute o seguinte comando:
- npx shipit production deploy
O resultado desse comando (que é grande demais para ser incluído por completo) fornece detalhes sobre as tarefas que estão sendo executadas e o resultado da função específica. O resultado que se segue à tarefa pm2-server
mostra que o app Node.js foi iniciado:
OutputRunning 'deploy:init' task...
Finished 'deploy:init' after 432 μs
. . .
Running 'pm2-server' task...
Running "pm2 delete -s hello || :" on host "centos-ap-app.asciant.com".
Running "pm2 start /home/deployer/example.com/shared/ecosystem.config.js --env production --watch true" on host "centos-ap-app.asciant.com".
@centos-ap-app.asciant.com [PM2][WARN] Node 4 is deprecated, please upgrade to use pm2 to have all features
@centos-ap-app.asciant.com [PM2][WARN] Applications hello not running, starting...
@centos-ap-app.asciant.com [PM2] App [hello] launched (1 instances)
@centos-ap-app.asciant.com ┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────┬──────────┐
@centos-ap-app.asciant.com │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
@centos-ap-app.asciant.com ├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────┼──────────┤
@centos-ap-app.asciant.com │ hello │ 0 │ 1.0.0 │ fork │ 4177 │ online │ 0 │ 0s │ 0% │ 4.5 MB │ deployer │ enabled │
@centos-ap-app.asciant.com └──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────┴──────────┘
@centos-ap-app.asciant.com Use `pm2 show <id|name>` to get more details about an app
Finished 'pm2-server' after 5.27 s
Running 'deploy:clean' task...
Keeping "5" last releases, cleaning others
Running "(ls -rd /home/deployer/example.com/releases/*|head -n 5;ls -d /home/deployer/example.com/releases/*)|sort|uniq -u|xargs rm -rf" on host "centos-ap-app.asciant.com".
Finished 'deploy:clean' after 1.81 s
Running 'deploy:finish' task...
Finished 'deploy:finish' after 222 μs
Finished 'deploy' [ deploy:init, deploy:fetch, deploy:update, deploy:publish, deploy:clean, deploy:finish ]
Para visualizar seu aplicativo como um usuário visualizaria, você pode digitar a URL your-domain
do seu site em seu navegador para acessar o servidor web. Isso servirá o aplicativo Node.js, por proxy reverso, no servidor app, onde seus arquivos foram implantados.
Você verá uma saudação Hello World.
Nota: após a primeira implantação, seu repositório Git irá rastrear um arquivo recém-criado, chamado ecosystem.config.js
. Como esse arquivo será recompilado a cada implantação, podendo conter segredos do aplicativo compilado, ele deve ser adicionado ao arquivo .gitignore
, no diretório raiz do aplicativo em sua máquina local, antes da sua próxima confirmação do git
.
. . .
# ecosystem.config
ecosystem.config.js
Você implantou seu aplicativo Node.js em seu servidor app, que se refere à sua nova implantação. Com tudo em funcionamento, você pode prosseguir com o monitoramento dos processos do seu aplicativo.
O PM2 é uma ótima ferramenta para gerenciar seus processos remotos, mas também fornece recursos para monitorar o desempenho desses processos do aplicativo.
Conecte-se ao seu servidor app remoto via SSH com este comando:
- ssh deployer@your_app_server_ip
Para obter informações específicas relacionadas aos seus processos gerenciados pelo PM2, execute o seguinte:
- pm2 list
Você verá um resultado parecido com este:
Output┌─────────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬──────┬───────────┬──────────┬──────────┐
│ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
├─────────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼──────┼───────────┼──────────┼──────────┤
│ hello │ 0 │ 0.0.1 │ fork │ 3212 │ online │ 0 │ 62m │ 0.3% │ 45.2 MB │ deployer │ enabled │
└─────────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴──────┴───────────┴──────────┴──────────┘
Você verá um resumo das informações que o PM2 coletou. Para ver informações detalhadas, execute:
- pm2 show hello
O resultado dá mais detalhes sobre as informações do resumo fornecidas pelo comando pm2 list
. Ele também fornece informações sobre vários comandos auxiliares e fornece os locais dos arquivos de registro:
Output Describing process with id 0 - name hello
┌───────────────────┬─────────────────────────────────────────────────────────────┐
│ status │ online │
│ name │ hello │
│ version │ 1.0.0 │
│ restarts │ 0 │
│ uptime │ 82s │
│ script path │ /home/deployer/example.com/releases/20190531213027/hello.js │
│ script args │ N/A │
│ error log path │ /home/deployer/.pm2/logs/hello-error.log │
│ out log path │ /home/deployer/.pm2/logs/hello-out.log │
│ pid path │ /home/deployer/.pm2/pids/hello-0.pid │
│ interpreter │ node │
│ interpreter args │ N/A │
│ script id │ 0 │
│ exec cwd │ /home/deployer │
│ exec mode │ fork_mode │
│ node.js version │ 4.2.3 │
│ node env │ production │
│ watch & reload │ ✔ │
│ unstable restarts │ 0 │
│ created at │ 2019-05-31T21:30:48.334Z │
└───────────────────┴─────────────────────────────────────────────────────────────┘
Revision control metadata
┌──────────────────┬────────────────────────────────────────────────────┐
│ revision control │ git │
│ remote url │ N/A │
│ repository root │ /home/deployer/example.com/releases/20190531213027 │
│ last update │ 2019-05-31T21:30:48.559Z │
│ revision │ 62fba7c8c61c7769022484d0bfa46e756fac8099 │
│ comment │ Our first commit │
│ branch │ master │
└──────────────────┴────────────────────────────────────────────────────┘
Divergent env variables from local env
┌───────────────────────────┬───────────────────────────────────────┐
│ XDG_SESSION_ID │ 15 │
│ HOSTNAME │ N/A │
│ SELINUX_ROLE_REQUESTED │ │
│ TERM │ N/A │
│ HISTSIZE │ N/A │
│ SSH_CLIENT │ 44.222.77.111 58545 22 │
│ SELINUX_USE_CURRENT_RANGE │ │
│ SSH_TTY │ N/A │
│ LS_COLORS │ N/A │
│ MAIL │ /var/mail/deployer │
│ PATH │ /usr/local/bin:/usr/bin │
│ SELINUX_LEVEL_REQUESTED │ │
│ HISTCONTROL │ N/A │
│ SSH_CONNECTION │ 44.222.77.111 58545 209.97.167.252 22 │
└───────────────────────────┴───────────────────────────────────────┘
. . .
O PM2 também fornece uma ferramenta de monitoramento dentro do terminal, que pode ser acessada com:
- pm2 monit
O resultado desse comando é um painel interativo, onde o pm2
fornece informações de processo, registros, métricas e metadados em tempo real. Este painel pode ajudar no monitoramento de recursos e registros de erro:
Output┌─ Process list ────────────────┐┌─ Global Logs ─────────────────────────────────────────────────────────────┐
│[ 0] hello Mem: 22 MB ││ │
│ ││ │
│ ││ │
└───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘
┌─ Custom metrics (http://bit.l─┐┌─ Metadata ────────────────────────────────────────────────────────────────┐
│ Heap Size 10.73 ││ App Name hello │
│ Heap Usage 66.14 ││ Version N/A │
│ Used Heap Size 7.10 ││ Restarts 0 │
│ Active requests 0 ││ Uptime 55s │
│ Active handles 4 ││ Script path /home/asciant/hello.js │
│ Event Loop Latency 0.70 ││ Script args N/A │
│ Event Loop Latency p95 ││ Interpreter node │
│ ││ Interpreter args N/A │
└───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘
Com uma compreensão sobre como você pode monitorar seus processos com o PM2, você pode prosseguir e ver como o Shipit pode ajudar na reversão para uma implantação anterior em funcionamento.
Termine sua sessão ssh
no seu servidor app executando exit
.
Às vezes, as implantações revelam bugs imprevistos, ou problemas que fazem com que seu site falhe. Os desenvolvedores e mantenedores do Shipit previram esse problema e proporcionaram a capacidade de se fazer a reversão para implantações anteriores (em funcionamento) do seu aplicativo.
Para garantir que sua configuração PM2
permaneça, adicione outro ouvinte de eventos ao shipitfile.js
no evento rollback
(reversão):
. . .
shipit.on('rollback', () => {
shipit.start('npm-install', 'copy-config');
});
Adicione um ouvinte ao evento rollback
para executar suas tarefas npm-install
e copy-config
. Isso é necessário, pois, ao contrário do evento published
, o evento updated
não é executado pelo ciclo de vida do Shipit quando se reverte uma implantação. Adicionar esse ouvinte de eventos garante que seu gerenciador de processos PM2
apontará para a implantação mais recente, mesmo no caso de uma reversão.
Esse processo é semelhante ao da implantação, com uma pequena alteração no comando. Para tentar reverter para uma implantação anterior, execute o seguinte:
- npx shipit production rollback
Assim como o comando deploy
, o rollback
fornece detalhes sobre o processo de reversão e as tarefas que estão sendo executadas:
OutputRunning 'rollback:init' task...
Get current release dirname.
Running "if [ -h /home/deployer/example.com/current ]; then readlink /home/deployer/example.com/current; fi" on host "centos-ap-app.asciant.com".
@centos-ap-app.asciant.com releases/20190531213719
Current release dirname : 20190531213719.
Getting dist releases.
Running "ls -r1 /home/deployer/example.com/releases" on host "centos-ap-app.asciant.com".
@centos-ap-app.asciant.com 20190531213719
@centos-ap-app.asciant.com 20190531213519
@centos-ap-app.asciant.com 20190531213027
Dist releases : ["20190531213719","20190531213519","20190531213027"].
Will rollback to 20190531213519.
Finished 'rollback:init' after 3.96 s
Running 'deploy:publish' task...
Publishing release "/home/deployer/example.com/releases/20190531213519"
Running "cd /home/deployer/example.com && if [ -d current ] && [ ! -L current ]; then echo "ERR: could not make symlink"; else ln -nfs releases/20190531213519 current_tmp && mv -fT current_tmp current; fi" on host "centos-ap-app.asciant.com".
Release published.
Finished 'deploy:publish' after 1.8 s
Running 'pm2-server' task...
Running "pm2 delete -s hello || :" on host "centos-ap-app.asciant.com".
Running "pm2 start /home/deployer/example.com/shared/ecosystem.config.js --env production --watch true" on host "centos-ap-app.asciant.com".
@centos-ap-app.asciant.com [PM2][WARN] Node 4 is deprecated, please upgrade to use pm2 to have all features
@centos-ap-app.asciant.com [PM2][WARN] Applications hello not running, starting...
@centos-ap-app.asciant.com [PM2] App [hello] launched (1 instances)
@centos-ap-app.asciant.com ┌──────────┬────┬─────────┬──────┬──────┬────────┬─────────┬────────┬─────┬──────────┬──────────┬──────────┐
@centos-ap-app.asciant.com │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │
@centos-ap-app.asciant.com ├──────────┼────┼─────────┼──────┼──────┼────────┼─────────┼────────┼─────┼──────────┼──────────┼──────────┤
@centos-ap-app.asciant.com │ hello │ 0 │ 1.0.0 │ fork │ 4289 │ online │ 0 │ 0s │ 0% │ 4.5 MB │ deployer │ enabled │
@centos-ap-app.asciant.com └──────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴─────┴──────────┴──────────┴──────────┘
@centos-ap-app.asciant.com Use `pm2 show <id|name>` to get more details about an app
Finished 'pm2-server' after 5.55 s
Running 'deploy:clean' task...
Keeping "5" last releases, cleaning others
Running "(ls -rd /home/deployer/example.com/releases/*|head -n 5;ls -d /home/deployer/example.com/releases/*)|sort|uniq -u|xargs rm -rf" on host "centos-ap-app.asciant.com".
Finished 'deploy:clean' after 1.82 s
Running 'rollback:finish' task...
Finished 'rollback:finish' after 615 μs
Finished 'rollback' [ rollback:init, deploy:publish, deploy:clean, rollback:finish ]
Você configurou o Shipit para manter 5 versões de lançamento, através da configuração de keepReleases: 5
no shipitfile.js
. O Shipit monitora essas versões internamente para garantir a capacidade de reverter quando necessário. O Shipit também fornece uma maneira conveniente de identificar as versões, criando um diretório nomeado na forma de um carimbo de data/hora (YYYYMMDDHHmmss - Exemplo: /home/deployer/your-domain/releases/20190420210548
).
Se quisesse personalizar ainda mais o processo de reversão, você poderia ouvir eventos específicos para a operação de reversão. Na sequência, você poderá usar esses eventos para executar tarefas que irão complementar sua reversão. Você pode consultar a lista de eventos fornecida no detalhamento do ciclo de vida do Shipit e configurar as tarefas/ouvintes dentro do seu shipitfile.js
.
Capacidade de reversão significa que sempre será possível oferecer aos seus usuários uma versão do seu aplicativo que funcione, mesmo se uma implantação introduzir erros/problemas inesperados.
Neste tutorial, você configurou um fluxo de trabalho que permite que crie uma alternativa altamente personalizável da Plataforma como um Serviço, tudo a partir de alguns servidores. Esse fluxo de trabalho leva em consideração implantações e configurações personalizadas, o monitoramento de processos com o PM2, a possibilidade de dimensionar e adicionar serviços, servidores adicionais ou ambientes à implantação, quando necessário.
Se estiver interessado em continuar no desenvolvimento de suas habilidades com o Node.js, confira o material sobre Node.js da DigitalOcean, bem como a série sobre Como programar no Node.js.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!