Dockerizar una aplicación nodejs: ¿debería funcionar pm2 ls cuando inicio el contenedor por primera vez?

Aug 18 2020

Tengo la siguiente aplicación express / node:

FROM node:12
WORKDIR /usr/share/jtapp
COPY  package*.json ./
RUN apt-get update
RUN apt-get install -y net-tools
RUN npm install
RUN npm install pm2@latest -g
#RUN npm ci --only=production
COPY . .
EXPOSE 3000
RUN pm2 start server.js

Parece construir bien. Pero cuando inicio la imagen y la adjunto a través de bash, no hay procesos pm2 en ejecución.

Estos son los resultados de la compilación:

Sending build context to Docker daemon  319.5kB                                                                                                                                                                                              Step 1/10 : FROM node:12                                                                                                                                                                                                                      ---> cfcf3e70099d                                                                                                                                                                                                                           Step 2/10 : WORKDIR /usr/share/jtapp                                                                                                                                                                                                     ---> Using cache                                                                                                                                                                                                                             ---> 2c2e2e1e92f2                                                                                                                                                                                                                           Step 3/10 : COPY  package*.json ./                                                                                                                                                                                                            ---> Using cache                                                                                                                                                                                                                             ---> 57829fd5e9d7                                                                                                                                                                                                                           Step 4/10 : RUN apt-get update                                                                                                                                                                                                                ---> Using cache                                                                                                                                                                                                                             ---> c0bbfed43ca8                                                                                                                                                                                                                           Step 5/10 : RUN apt-get install -y net-tools                                                                                                                                                                                                  ---> Using cache                                                                                                                                                                                                                             ---> 0b34759d8298                                                                                                                                                                                                                           Step 6/10 : RUN npm install                                                                                                                                                                                                                   ---> Using cache                                                                                                                                                                                                                             ---> 6abc42a9f8a3                                                                                                                                                                                                                           Step 7/10 : RUN npm install pm2@latest -g                                                                                                                                                                                                     ---> Running in 2fafacd302bf                                                                                                                                                                                                                /usr/local/bin/pm2 -> /usr/local/lib/node_modules/pm2/bin/pm2                                                                                                                                                                                /usr/local/bin/pm2-dev -> /usr/local/lib/node_modules/pm2/bin/pm2-dev                                                                                                                                                                        /usr/local/bin/pm2-docker -> /usr/local/lib/node_modules/pm2/bin/pm2-docker                                                                                                                                                                  /usr/local/bin/pm2-runtime -> /usr/local/lib/node_modules/pm2/bin/pm2-runtime               
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/pm2/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ [email protected]
added 185 packages from 191 contributors in 10.165s
Removing intermediate container 2fafacd302bf
 ---> 11d15b993ca2
Step 8/10 : COPY . .
 ---> efab8283bbd9
Step 9/10 : EXPOSE 3000
 ---> Running in aae343a75727
Removing intermediate container aae343a75727
 ---> b97825863317
Step 10/10 : RUN pm2 start server.js
 ---> Running in f0d14c61a3a6
[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /usr/share/jtapp/server.js in fork_mode (1 instance)
[PM2] Done.
┌─────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼───────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0   │ server    │ default     │ 1.0.0   │ fork    │ 28       │ 0s     │ 0    │ online    │ 0%       │ 28.2mb   │ root     │ disabled │
└─────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
Removing intermediate container f0d14c61a3a6
 ---> 859f8479f3a6
Successfully built 859f8479f3a6

Entonces así es como inicio el contenedor y lo adjunto:

lab:/var/lib/git/jtapp# docker run -d -it --name jtapp -p 3000:3000 jtapp bash
d62927716ab593376c4e38f7d4d05007223ce2adfcb4997e722b81ad7260f114
lab:/var/lib/git/jtapp # docker exec -it jtapp  bash
root@d62927716ab5:/usr/share/jtapp # pm2
usage: pm2 [options] <command>

pm2 -h, --help             all available commands and options
pm2 examples               display pm2 usage examples
pm2 <command> -h           help on a specific command

Access pm2 files in ~/.pm2
root@d62927716ab5:/usr/share/jtapp #

Pero puedo comenzar todo manualmente una vez que estoy dentro del contenedor, así:

root@d62927716ab5:/usr/share/jtapp# pm2 start server.js
[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /usr/share/jtapp/server.js in fork_mode (1 instance)
[PM2] Done.
┌─────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼───────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0   │ server    │ default     │ 1.0.0   │ fork    │ 37       │ 0s     │ 0    │ online    │ 0%       │ 28.4mb   │ root     │ disabled │
└─────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

EDITAR 1

Cambiado:

 RUN pm2 start server.js 

a

 CMD ["pm2", "start", "server.js"]

Y luego traté de reconstruir / iniciar un contenedor. cuando hago un "pm2 ls", todavía vuelve vacío.

root@a8b7eb21d307:/usr/share/jtapp# pm2 ls
[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
┌────┬────────────────────┬──────────┬──────┬───────────┬──────────┬──────────┐
│ id │ name               │ mode     │ ↺    │ status    │ cpu      │ memory   │
└────┴────────────────────┴──────────┴──────┴───────────┴──────────┴──────────┘

EDITAR 2

Cuando elimino la opción "-d" en mi comando de ejecución:

lab:/var/lib/git/jtappd# docker run  -it --name jtapp -p 3000:3000 jtapp  bash
root@3cf4855372ec:/usr/share/jtapp# pm2 ls
[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
┌─────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
└─────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
root@3cf4855372ec:/usr/share/jtapp#

EDITAR 3

Entonces el Dockerfile se ve así ahora:

FROM node:12
WORKDIR /usr/share/jtapp
COPY  package*.json ./
RUN apt-get update
RUN apt-get install -y net-tools
RUN npm install
RUN npm install pm2@latest -g
COPY . .
EXPOSE 3000
CMD ["npm", "run", "start:pm2"]

ecosistema.config.js se ve así:

lab:/var/lib/git/jtapp# cat ecosystem.config.js
module.exports = {
  apps: [{
    name: 'jtapp',
    script: './server.js', //entrypoint
    instances: 1,
    autorestart: true, // pm2 to restart if this app fails/stops
    max_memory_restart: '1G'
  }]
}

y la sección de script de package.json:

 1 {
 2   "name": "nodeserver",
 3   "version": "1.0.0",
 4   "description": "simple node server",
 5   "main": "index.js",
 6   "scripts": {
 7     "test": "echo \"Error: no test specified\" && exit 1",
 8     "start": "nodemon server.js",
 9     "start:pm2": "pm2 start ecosystem.config.js --no-daemon"
10   },

El Dockerfile se compila sin errores. Pero cuando inicio el contenedor ... server.js no se está ejecutando. pm2 está instalado.

Pero no hay problemas para iniciarlo manualmente usando el archivo de ecosistema una vez que inicie sesión en el contenedor, como puede ver a continuación:

root@d51117d757a3:/usr/share/jtapp# pm2 start ecosystem.config.js
[PM2][WARN] Applications jtapp not running, starting...
[PM2] App [jtapp ] launched (1 instances)
┌─────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name     │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0   │ jtapp    │ default     │ 1.0.0   │ cluster │ 36       │ 0s     │ 0    │ online    │ 0%       │ 32.6mb   │ root     │ disabled │
└─────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

Respuestas

1 MohamadrezaRahimianGolkhandani Aug 19 2020 at 09:17

El mejor enfoque sería utilizar ecosystem.config.js. Coloque este archivo en el directorio raíz de su proyecto:


module.exports = {
  apps: [{
    name: 'app',
    script: 'src/index.js', // Your entry point
    instances: 1,
    autorestart: true, // THIS is the important part, this will tell PM2 to restart your app if it falls over
    max_memory_restart: '1G'
  }]
}

luego instale pm2 como módulo npm en su proyecto y agregue este script a su package.json

...
scripts: {
...
  "start:pm2":"pm2 start ecosystem.config.js --no-daemon"
}

y finalmente use este CMD en su dockerfile

CMD [ "npm", "run", "start:pm2" ]

EDITAR 1

puede encontrar un proyecto de muestra aquí con el archivo dockerfile original:

https://github.com/golkhandani/pm2_docker/tree/master

EDITAR 2

Acabo de probar el repositorio con otro Manjarolinux y aquí están los comandos

git clone https://github.com/golkhandani/pm2_docker.git

docker build pm2_docker/ --tag pm2docker:test

docker run -p 3000:3000 -t pm2docker:test

el -p 3000:3000argumento debe agregarse para acceder localmente a su servidor.

estas son capturas de pantalla adicionales que muestran comandos y resultados: