Search code examples
node.jsdockerdocker-composepm2

Can't install pm2 globally inside a docker container (Vultr host)


I'm trying to use docker-compose in a Vultr server with Ubuntu 18.04. I created the following Dockerfile:

FROM node:latest

# Create app directory
WORKDIR /usr/src/app

# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./

RUN npm install -g pm2
RUN npm install
# If you are building your code for production
# RUN npm install --only=production

# Bundle app source
COPY . .

EXPOSE 80
CMD [ "pm2-runtime", "server.js", "--watch" ]

And the docker-compose.yml file is:

version: '3'

services:
  nginx:
    image: nginx:latest
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - 80:80
    networks:
      - backbone
  web:
    build: ./../services/web
    volumes:
      - ./../services/web:/usr/src/app
    networks:
      - backbone
  edu_entities:
    build: ./../services/edu_entities
    volumes:
      - ./../services/edu_entities:/usr/src/app
    networks:
      - backbone
networks:
  backbone:
    driver: bridge

The output I get is the following:

root@vultr-host:~/app/config# docker-compose build
nginx uses an image, skipping
Building edu_entities
Step 1/8 : FROM node:latest
 ---> 37f455de4837
Step 2/8 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 282a6fa7bf8a
Step 3/8 : COPY package*.json ./
 ---> Using cache
 ---> 8b6970aecfec
Step 4/8 : RUN npm install pm2
 ---> Running in 2449fb50b303
npm WARN edu_entities@1.0.0 No description
npm WARN edu_entities@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ pm2@3.2.3
added 404 packages from 315 contributors and audited 2675 packages in 28.626s
found 0 vulnerabilities

Removing intermediate container 2449fb50b303
 ---> 5c33d7153e3c
Step 5/8 : RUN npm install
 ---> Running in 0f0a26e6ad00
audited 2675 packages in 5.301s
found 0 vulnerabilities

npm WARN edu_entities@1.0.0 No description
npm WARN edu_entities@1.0.0 No repository field.                                                                      
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules/fsevents):                               
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})                                                                           

Removing intermediate container 0f0a26e6ad00
 ---> ff9817b28907
Step 6/8 : COPY . .
 ---> 373ed677369f
Step 7/8 : EXPOSE 80
 ---> Running in bf44032ac43e
Removing intermediate container bf44032ac43e
 ---> 60ed79bedc2a
Step 8/8 : CMD [ "pm2-runtime", "server.js", "--watch" ]
 ---> Running in 9487a4f0fc5d
Removing intermediate container 9487a4f0fc5d
 ---> cdac633adfb8
Successfully built cdac633adfb8
Successfully tagged config_edu_entities:latest
Building web
Step 1/8 : FROM node:latest
 ---> 37f455de4837
Step 2/8 : WORKDIR /usr/src/app
 ---> Using cache
 ---> 282a6fa7bf8a
Step 3/8 : COPY package*.json ./
 ---> 8943e5aeb3c4
Step 4/8 : RUN npm install pm2
 ---> Running in 4dc7c76fb478

Then it stays here for a long time and...

Killed
ERROR: Service 'web' failed to build: The command '/bin/sh -c npm install pm2' returned a non-zero code: 137

I tried adding the flags -g and --unsafe-perm at RUN npm install pm2, both by themselves and separately. I also tried adding USER node in each Dockerfile and it didn't work either.

My file structure is the following:

.
├── config
│   ├── bin
│   │   └── ...
│   ├── docker-compose.yml
│   └── nginx
│       └── default.conf
└── services
    ├── edu_entities
    │   ├── Dockerfile
    │   ├── package-lock.json
    │   ├── package.json
    │   ├── server.js
    │   └── src
    │       └── ...
    └── web
        ├── Dockerfile
        ├── package-lock.json
        ├── package.json
        ├── server.js
        └── src
            └── ...

Edit: As @codestation said in the comments, it might have been a lack of free RAM in the host VM. I tried running docker-compose build this morning and it worked. However, now the following error appears:

root@vultr-host:~/app/config# docker-compose up
Starting config_nginx_1 ... 
Starting config_web_1 ... 
Starting config_nginx_1
Starting config_web_1 ... error

ERROR: for config_web_1  Cannot start service web: OCI runtime create failed: container_linux.go:348: starting contain
Starting config_nginx_1 ... done

ERROR: for web  Cannot start service web: OCI runtime create failed: container_linux.go:348: starting container process caused "exec: \"pm2-runtime\": executable file not found in $PATH": unknown
ERROR: Encountered errors while bringing up the project.

Edit 2: Turns out I necessarily had to add the -g flag in RUN npm install pm2. Then I encountered another error, which was that the container couldn't find express. I solved it by running npm install from the local machine (outside the container) and the volume configuration managed to sync the node_modules folder into the container.


Solution

  • The initial error was that the Vultr Host VM not had enough RAM available, so docker-compose build failed when it had to install pm2. Then, I also had to add the -g flag in RUN npm install pm2 at my service's Dockerfile. I also had to run npm install outside the container to add the other dependencies and let the volume put them into the container.

    After all this, NGINX was able to serve the page and now it's up and running. :)