El autor seleccionó la Electronic Frontier Foundation para recibir una donación como parte del programa Write for DOnations.
Shipit es una herramienta universal de automatización e implementación para desarrolladores de Node.js. Incluye un flujo de tareas basado en el popular paquete Orchestrator, comandos de inicio de sesión y SSH interactivos a través de OpenSSH y una API extensible. Los desarrolladores pueden usar Shipit a fni de automatizar flujos de trabajo de compilación e implementación para una amplia variedad de aplicaciones de Node.js.
El flujo de trabajo de Shipit no solo permite a los desarrolladores configurar tareas, sino también especificar su orden de ejecución; si deben ejecutarse de forma sincrónica o asincrónica y en qué entorno.
En este tutorial, instalará y configurará Shipit para implementar una aplicación de Node.js de su entorno de desarrollo local en su entorno de producción. Usará Shipit para implementar su aplicación y configurar el servidor remoto haciendo lo siguiente:
rsync
, git
y ssh
);Antes de iniciar este tutorial, necesitará lo siguiente:
rsync
y git
instalados.
git
en distribuciones de Linux, siga el tutorial Cómo instalar Git.git
. En este tutorial se usará GitHub.Nota: Los usuarios de Windows deberán instalar el subsistema de Windows para Linux para ejecutar los comandos de esta guía.
En Shipit se requiere un repositorio de Git para la sincronía entre la máquina de desarrollo local y el servidor remoto. En este paso, creará un repositorio remoto en Github.com
. Si bien cada proveedor es ligeramente diferente, los comandos pueden ser transferibles.
Para crear un repositorio, abra Github.com
en su navegador web e inicie sesión. Verá un símbolo + en la esquina superior derecha de cualquier página. Haga clic en + y luego en New repository.
Ingrese un nombre corto y recordable para su repositorio; por ejemplo, hello-world
. Tenga en cuenta que cualquier nombre que elija aquí se replicará como la carpeta del proyecto a partir de la que trabajará en su máquina local.
De manera opcional, puede añadir una descripción de su repositorio.
Según su preferencia, fije la visibilidad de su repositorio de modo que sea público o privado.
Asegúrese de que este se inicialice con .gitignore
; seleccione Node
en la lista desplegable Add .gitignore
. Este paso es importante para evitar que se añadan archivos innecesarios (por ejemplo, la carpeta node_modules
) a su repositorio.
Haga clic en el botón Create repository.
Ahora, el repositorio debe clonarse de Github.com
y enviarse a su equipo local.
Abra su terminal y diríjase a la ubicación en la que desee almacenar todos los archivos de su proyecto de Node.js. Tenga en cuenta que en este proceso se creará una subcarpeta dentro del directorio actual. Para clonar el repositorio en su máquina local, ejecute el siguiente comando:
- git clone https://github.com/your-github-username/your-github-repository-name.git
Deberá sustituir your-github-username
y your-github-repository-name
para reflejar su nombre de usuario de Github y el nombre del repositorio previamente suministrado.
Nota: Si habilitó la autenticación de dos factores (2FA) en Github.com
, debe usar un token de acceso personal o una clave SSH en lugar de su contraseña cuando acceda a Github en la línea de comandos. En la página de ayuda de Github relacionada con 2FA se proporciona más información.
Verá un resultado similar a lo siguiente:
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.
Diríjase al repositorio ejecutando el siguiente comando:
- cd your-github-repository-name
En el repositorio se encuentra un solo archivo y una carpeta, ambos son archivos que Git utiliza para administrar el repositorio. Puede verificar esto con lo siguiente:
- ls -la
Visualizará un resultado similar al siguiente:
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
Ahora que configuró un repositorio git
funcional, creará el archivo shipit.js
que administra su proceso de implementación.
En este paso, creará un proyecto de ejemplo de Node.js y luego agregará los paquetes de Shipit. En este tutorial se ofrece una aplicación de ejemplo: el servidor web Node.js que acepta solicitudes HTTP y responde con Hello World
en texto simple. Para crear la aplicación, ejecute el siguiente comando:
- nano hello.js
Añada el siguiente código de aplicación de ejemplo a hello.js
(actualizando la variable APP_PRIVATE_IP_ADDRESS
de modo que sea la dirección IP privada de su servidor 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/');
Ahora, cree el archivo package.json
para su aplicación:
- npm init -y
Con este comando se crea un archivo package.json
, que usará para configurar su aplicación Node.js. En el siguiente paso, agregará dependencias a este archivo con la interfaz de línea de comandos 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"
}
A continuación, instale los paquetes npm
necesarios con el siguiente comando:
- npm install --save-dev shipit-cli shipit-deploy shipit-shared
Aquí se utiliza el indicador --save-dev
, ya que los paquetes de Shipit solo son necesarios en su equipo local. Visualizará un resultado similar al siguiente:
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
Con esto también se añadieron los tres paquetes a su archivo package.json
como dependencias de desarrollo:
. . .
"devDependencies": {
"shipit-cli": "^4.2.0",
"shipit-deploy": "^4.1.4",
"shipit-shared": "^4.4.2"
},
. . .
Ahora que configuró su entorno local, podrá proceder a preparar el servidor app remoto para las implementaciones basadas en Shipit.
En este paso, usará ssh
para establecer conexión con el servidor app e instalará la dependencia remota rsync
. Rsync es una utilidad que permite transferir y sincronizar de manera eficiente archivos entre unidades de máquinas locales y en computadoras en red mediante la comparación de fechas de modificación y tamaños de archivos.
En Shipit se utiliza rsync
para transferir y sincronizar archivos entre su equipo local y el servidor app remoto. No emitirá comandos para rsync
de forma directa; Shipit lo hará por usted.
Nota: A través de Cómo configurar una aplicación de Node.js para la producción en CentOS 7, obtuvo dos servidores app y web. Estos comandos deben ejecutarse únicamente en app.
Establezca conexión con su servidor app
remoto a través de ssh:
- ssh deployer@your_app_server_ip
Instale rsync
en su servidor ejecutando el siguiente comando:
- sudo yum install rsync
Confirme la instalación con lo siguiente:
- rsync --version
Verá una línea similar en el resultado de este comando:
Outputrsync version 3.1.2 protocol version 31
. . .
Puede cerrar su sesión ssh
escribiendo exit
.
Con rsync
instalado y disponible en la línea de comandos, puede proceder con las tareas de implementación y su relación con los eventos.
Tanto los eventos como las tareas son componentes claves de las implementaciones de Shipit y es importante comprender la forma en que complementan la implementación de su aplicación. Los eventos desencadenados por Shipit representan puntos específicos en el ciclo de vida de la implementación. Sus tareas se ejecutarán en respuesta a estos eventos, según la secuencia del ciclo de vida de Shipit.
Un ejemplo común de la utilidad de este sistema de tareas y eventos en una aplicación de Node.js se encuentra en la instalación de las dependencias de la aplicación (node_modules
) en el servidor remoto. Más adelante en este paso, hará que en Shipit se escuche el evento updated
(emitido después de que los archivos de la aplicación se transfieren) y ejecutará una tarea para instalar las dependencias de la aplicación (npm install
) en el servidor remoto.
Para escuchar los eventos y ejecutar tareas, Shipit necesita un archivo de configuración que contenga información sobre su servidor remoto (app) y registre las escuchas de eventos y los comandos que estas tareas ejecutarán. Este archivo reside en su máquina de desarrollo local, dentro del directorio de su aplicación de Node.js.
Para comenzar, cree este archivo; incluyea información sobre su servidor remoto, las escuchas de eventos a las que desee suscribirse y algunas definiciones de sus tareas. Cree shipitfile.js
dentro del directorio root de su aplicación, en su máquina local, ejecutando el siguiente comando:
- nano shipitfile.js
Ahora que creó un archivo, este debe completarse con la información inicial de entorno que Shipit requiere. Esta consiste principalmente en la ubicación de su repositorio Git
remoto y, lo que es más importante, la dirección IP pública y la cuenta de usuario SSH de su servidor app.
Añada esta configuración inicial y actualice las líneas resaltadas para que coincidan con su entorno:
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
};
La actualización de las variables en su método shipit.initConfig
proporciona a Shipit la configuración específica para su implementación. Estas representan lo siguiente para Shipit:
deployTo:
es el directorio en el que Shipit implementará el código de su aplicación en el servidor remoto. En este caso, se utiliza la carpeta /home/
para un usuario no root con privilegios sudo
(/home/sammy
) debido a que es segura y evitará problemas con los permisos. El componente /your-domain
es una convención de nomenclatura para distinguir la carpeta de otras dentro de la carpeta de inicio del usuario.repositoryUrl:
es la URL para el repositorio completo de Git; en Shipit se utilizará esta URL para garantizar que los archivos del proyecto se encuentren en sincronización antes de la implementación.keepReleases:
es el número de versiones que se deben mantener en el servidor remoto. release
es una carpeta fechada que contiene los archivos de su aplicación en el momento de su lanzamiento. Puede ser útil para un rollback
de una implementación.shared:
es la configuración que se corresponde con keepReleases
y permite que los directorios sean shared
entre las versiones. En este caso, tenemos una sola carpeta node_modules
que comparten todas las versiones.production:
representa un servidor remoto para la implementación de su aplicación. En este caso, tiene un único servidor (app) al que asignó el nombre production
y la configuración los servers
: coincide con su public ip address
y user
de SSH. El nombre production
se corresponde con el comando de implementación de Shipit utilizado al final de este tutorial (npx shipit server name deploy
o, en su caso, npx shipit production deploy
).Se puede encontrar más información sobre el objeto de configuración de implementación de Shipit en el repositorio Shipit de Github.
Antes de continuar con la actualización de su shipitfile.js
, revisaremos el siguiente fragmento de código de ejemplo para entender las tareas de Shipit:
Example event listenershipit.on('deploy', () => {
shipit.start('say-hello');
});
shipit.blTask('say-hello', async () => {
shipit.local('echo "hello from your local computer"')
});
Esta es una tarea de ejemplo que utiliza el método shipit.on
para suscribirse al evento deploy
. Esta tarea se esperará que el ciclo de vida de Shipit emita el evento deploy
; luego, cuando se reciba el evento, en la tarea se ejecutará el método shipit.start
que indica a Shipit que aplique start
a la tarea say-hello
.
En el método shipit.on
se toman dos parámetros: el nombre del evento que se escuchará y la función de devolución de llamada que se ejecutará cuando se reciba el evento.
En la declaración del método shipit.on
, la tarea se define con el método shipit.blTask
. Esto crea una nueva tarea Shipit que bloqueará otras tareas durante su ejecución (es una tarea sincrónica). En el método shipit.blTask
también se toman dos parámetros: el nombre de la tarea que define y una función de devolución de llamada que se ejecutará una vez que shipit.start active la tarea
.
En la función de devolución de llamada de este ejemplo (say-hello
), método shipit.local
ejecuta un comando en la máquina local. En el comando local se emite “hello from your local computer”
en el resultado de la terminal.
Si quisiera ejecutar un comando en el servidor remoto, usaría el método shipit.remote
. Los dos métodos, shipit.local
y shipit.remote
, proporcionan una API para emitir comandos de forma local o remota como parte de una implementación.
Ahora, actualice shipitfile.js
para incluir las escuchas de eventos a fin de suscribirse al ciclo de vida de Shipit con shipit.on
. Añada las escuchas de eventos a su shipitfile.js
, e insértelos conforme al marcador de posición de comentarios de la configuración inicial // Our tasks will go here
:
. . .
shipit.on('updated', () => {
shipit.start('npm-install', 'copy-config');
});
shipit.on('published', () => {
shipit.start('pm2-server');
});
Estos dos métodos escuchan los eventos updated
y published
que se emiten como parte del ciclo de vida de implementación de Shipit. Cuando se reciba el evento, cada uno iniciará tareas usando el método shipit.start
, en un proceso similar al de la tarea de ejemplo.
Ahora que programó las escuchas, agregará la tarea correspondiente. Añada la siguiente tarea a su shipitfile.js
; insértelas después de las escuchas 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);
});
Primero declara una tarea llamada copy-config
. En esta tarea se crea un archivo local llamado ecosystem.config.js
y luego se copia ese archivo a su servidor de app remoto. En PM2
, este archivo se utiliza para administrar su aplicación de Node.js. Proporciona a PM2
la información necesaria sobre rutas de archivos para garantizar que se ejecuten los últimos archivos que implementó. Más adelante, en el proceso de compilación, creará una tarea que ejecuta PM2
con ecosystem.config.js
como configuración.
Si en su aplicación se necesitan variables de entorno (como una cadena de conexión de base de datos), puede declararlas de forma local, en env:
, o en el servidor remoto, en env_production:
, aplicando el mismo método con el que estableció la variable Node_ENV
en estos objetos.
Añada la siguiente tarea a su shipitfile.js
después de la tarea copy-config
:
. . .
shipit.blTask('npm-install', async () => {
shipit.remote(`cd ${shipit.releasePath} && npm install --production`);
});
A continuación, declare una tarea llamada npm-install
. En esta tarea se utiliza una terminal bash remota (a través de shipit.remote
) para instalar las dependencias de la aplicación (paquetes npm
).
Añada la última tarea a su shipitfile.js
después de la tarea 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 último, declare una tarea llamada pm2-server
. En esta tarea, también se utiliza una terminal bash remota para primero evitar que PM2
administre su implementación anterior a través del comando delete
y luego iniciar una nueva instancia de su servidor Node.js proporcionando el archivo ecosystem.config.js
como una variable. También se notifica a PM2
que debe usar variables de entorno del bloque production
en su configuración inicial y se solicita, también a PM2
, que controle la aplicación y la reinicie si falla.
El archivo shipitfile.js
completo:
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`
);
});
};
Guarde y cierre el archivo cuando esté listo.
Con su shipitfile.js
configurado, las escuchas de eventos y las tareas asociadas completadas, puede proceder con la implementación en el servidor app.
En este paso, implementará su aplicación de forma remota y verificará que la implementación haya permitido la disponibilidad de su aplicación en Internet.
Debido a que en Shipit se clonan los archivos de proyecto del repositorio remoto de Git, debe mover los archivos locales de su aplicación de Node.js de su máquina local a Github. Diríjase al directorio de la aplicación de su proyecto de Node.js (donde se ubican hello.js
y shiptitfile.js
) y ejecute el siguiente comando:
- git status
Con el comando git status
se muestra el estado del directorio de trabajo y el área de ensayos. Le permite ver los cambios que se prepararon o no, y los archivos que no se sometieron a seguimiento a través de Git. Sus archivos no se encuentran bajo seguimiento y aparecen en rojo en el 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)
Puede añadir estos archivos a su repositorio con el siguiente comando:
- git add --all
Con este comando no se produce ningún resultado, pero si ejecutara git status
de nuevo los archivos se mostrarían en verde con una nota que señalaría la necesidad de confirmar cambios.
Puede crear una confirmación ejecutando el siguiente comando:
- git commit -m "Our first commit"
En el resultado de este comando se proporciona información específica de Git sobre los archivos.
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
Lo único que queda por hacer ahora es enviar su confirmación al repositorio remoto para que Shipit realice una clonación a su servidor app durante la implementación. Ejecute el siguiente comando:
- git push origin master
En el resultado, se incluye información acerca de la sincronización con el repositorio 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 implementar su aplicación, ejecute el siguiente comando:
- npx shipit production deploy
En el resultado de este comando (que es demasiado largo para incluirlo en su totalidad) se proporcionan detalles sobre las tareas que se ejecutan y el resultado de la función específica. En el resultado que se observa a continuación para la tarea pm2-server
se muestra que la aplicación Node.js se ha 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 ver su aplicación como la vería un usuario, puede ingresar la URL de su sitio web your-domain
en su navegador a fin de acceder a su servidor web. Esto proporcionará la aplicación de Node.js, a través de un proxy inverso, en el servidor app en el que se implementaron sus archivos.
Verá un saludo Hello World.
Nota: Después de la primera implementación, en su repositorio de Git se hará un seguimiento de un archivo nuevo llamado ecosystem.config.js
. Debido a que este archivo se reconstruye en cada implementación y puede contener secretos de la aplicación compilados, se debe añadir al archivo .gitignore
en el directorio root de la aplicación de su máquina local antes de su próxima confirmación de git
.
. . .
# ecosystem.config
ecosystem.config.js
Implementó su aplicación Node.js en el servidor app, que hace referencia a su nueva implementación. Con todo configurado y en funcionamiento, puede proceder con la supervisión de los procesos de su aplicación.
PM2 es una excelente herramienta para administrar sus procesos remotos, pero también incluye funciones para controlar el rendimiento de estos procesos de aplicación.
Establezca conexión con su servidor app remoto mediante SSH con el siguiente comando:
- ssh deployer@your_app_server_ip
Para obtener información específica relacionada con los procesos administrados de PM2, ejecute lo siguiente:
- pm2 list
Verá un resultado similar a lo siguiente:
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 │
└─────────────┴────┴─────────┴──────┴──────┴────────┴─────────┴────────┴──────┴───────────┴──────────┴──────────┘
Verá un resumen de la información recopilada por PM2. Para ver información detallada, puede ejecutar lo siguiente:
- pm2 show hello
En el resultado, se amplía la información del resumen proporcionada por el comando pm2 list
. También proporciona información sobre varios comandos suplementarios y también la ubicación de los archivos 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 │
└───────────────────────────┴───────────────────────────────────────┘
. . .
Además, PM2 proporciona una herramienta de supervisión en terminal a la que es posible acceder con lo siguiente:
- pm2 monit
Como resultado de este comando se obtiene un panel interactivo, en el cual pm2
proporciona registros, métricas, metadatos e información sobre procesos en tiempo real. Este panel puede ser útil para controlar los recursos y registros de errores:
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 │
└───────────────────────────────┘└───────────────────────────────────────────────────────────────────────────┘
Al comprender la forma en la que puede supervisar sus procesos con PM2, ahora puede considerar la forma en la que Shipit puede asistir en la reversión a una implementación funcional anterior.
Finalice su sesión ssh
en su servidor app ejecutando exit
.
En las implementaciones, de tanto en tanto se exhiben errores imprevistos o problemas que pueden causar fallas en su sitio. Los desarrolladores y los encargados de mantenimiento de Shipit previeron esto y proporcionaron la capacidad de restablecer la implementación (funcional) anterior de su aplicación.
Para garantizar que su configuración de PM2
persista, añada otra escucha de eventos a shipitfile.js
en el evento rollback
.
. . .
shipit.on('rollback', () => {
shipit.start('npm-install', 'copy-config');
});
Debe añadir una escucha al evento rollback
para ejecutar sus tareas npm-install
y copy-config
. Esto se requiere porque, a diferencia del evento published
, el evento updated
no se ejecuta a través del ciclo de vida de Shipit cuando se revierte una implementación. Añadir esta escucha garantiza que su administrador de procesos PM2
se oriente hacia la implementación más reciente, incluso en caso de una reversión.
Este proceso es similar a la implementación, con un pequeño cambio de comando. Para intentar restablecer a una implementación anterior, puede ejecutar lo siguiente:
- npx shipit production rollback
Al igual que el comando deploy
, rollback
proporciona detalles sobre el proceso de reversión y las tareas que se ejecutan:
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 ]
Configuró Shipit para mantener 5 versiones a través del ajuste keepReleases: 5
en shipitfile.js
. Shipit realiza un seguimiento interno de estas versiones para garantizar que la reversión sea posible cuando se necesite. Shipit también proporciona una alternativa práctica para identificar las versiones creando un directorio con el nombre de una marca de tiempo (AAAAMMDDHHmmss; por ejemplo, /home/deployer/your-domain/releases/20190420210548
).
Si desea personalizar aún más el proceso de reversión, puede escuchar eventos específicos de la operación de reversión. Luego, puede utilizarlos para ejecutar tareas que complementarán su reversión. Puede consultar la lista de eventos proporcionada en el desglose del ciclo de vida de Shipit, y configurar las tareas y escuchas dentro de su shipitfile.js
.
La capacidad de reversión implica que siempre puede proporcionar a sus usuarios una versión funcional de su aplicación, incluso si en una implementación se producen errores o problemas inesperados.
A lo largo de este tutorial, configuró un flujo de trabajo que le permite crear una alternativa sumamente personalizable a las plataformas como servicio, todo ello desde algunos servidores. Este flujo de trabajo permite personalizar la implementación y la configuración, controlar procesos con PM2, escalar y agregar servicios, o contar con servidores o entornos adicionales en la implementación cuando sea necesario.
Si está interesado en continuar desarrollando sus aptitudes para Node.js, consulte el contenido de Node.js de DigtalOcean y la serie Cómo producir código en 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!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.