Dockerizing a NodeJS app: package.json works fine locally but not inside container

Viewed 2679

This is the package.json of my Node app:

{
    "name": "my-graphql-app",
    "version": "1.0.0",
    "description": "My Node GraphQL APP",
    "private": true,
    "license": "UNLICENSED",
    "scripts": {
        "start": "npm run run:watch",
        "build": "webpack",
        "build:watch": "webpack --watch",
        "run": "node ./dist/app.js",
        "run:watch": "nodemon ./dist/app.js"
    },
    "dependencies": {
        "@babel/core": "^7.8.4",
        "@babel/polyfill": "^7.8.3",
        "@babel/preset-env": "^7.8.4",
        "apollo-server-express": "^2.10.1",
        "babel-loader": "^8.0.6",
        "body-parser": "^1.19.0",
        "cors": "^2.8.5",
        "express": "^4.17.1",
        "graphql": "^14.6.0",
        "mysql2": "^2.1.0",
        "nodemon": "^2.0.2",
        "npm-run-all": "^4.1.5",
        "sequelize": "^5.21.5",
        "webpack-cli": "^3.3.11"
    },
    "devDependencies": {
        "webpack": "^4.41.6",
        "webpack-node-externals": "^1.7.2"
    }
}

This is working fine when I run npm install and npm start on my local machine (in case it matters, I am running it on Mac OS Catalina 10.15.3). My local node version is v11.10.1.

I am going crazy trying to make the same Node app work inside a docker container. I have made many different attempts, tweaking the package.json and Dockerfile, but I always end up with some npm install error or import error.

I am trying to spin up the containers (I also have a MySQL container) using docker-compose up --build.

This is my Dockerfile:

FROM node:12

EXPOSE 5000

WORKDIR /graphql_api

COPY package.json .
RUN npm install

COPY . /graphql_api

CMD npm start

This is my docker-compose.yml:

version: '3'
services:
    database:
        image: mysql:5.7
        environment:
            - 'MYSQL_ROOT_PASSWORD=pwd'
            - 'MYSQL_DATABASE=testdb'
            - 'MYSQL_USER=user'
            - 'MYSQL_PASSWORD=pwd'
        volumes:
            - ./db:/docker-entrypoint-initdb.d
        restart: always
        ports:
            - 8006:3306
    graphql_api:
        build: ./graphql_api
        container_name: graphql_api
        restart: always
        volumes:
            - ./graphql_api:/graphql_api
            - /graphql_api/node_modules
        ports:
            - "5000:5000"
        depends_on:
            - database

(The MySQL container starts up perfectly fine, by the way, and the database itself is correctly initialised with the all the tables I have defined in my init.sql file.)

As soon as the build process reaches the RUN npm install point, I always get this warning:

npm WARN deprecated core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.

Then I get a bunch of messages like these ones

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/watchpack/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: abbrev@1.1.1 (node_modules/watchpack/node_modules/fsevents/node_modules/abbrev):
npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/graphql_api/node_modules/watchpack/node_modules/fsevents/node_modules/abbrev' -> '/graphql_api/node_modules/watchpack/node_modules/fsevents/node_modules/.abbrev.DELETE'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ansi-regex@2.1.1 (node_modules/watchpack/node_modules/fsevents/node_modules/ansi-regex):

(I didn't copypaste them all because there are really a lot.)

After those I get the message

added 785 packages from 486 contributors and audited 8930 packages in 26.85s

which makes me think that npm install did in fact have some effect despite the previous messages.

However, when the build process reaches the CMD npm start, this happens:

graphql_api    | > my-graphql-app@1.0.0 start /graphql_api
graphql_api    | > npm-run-all --parallel build:watch run:watch
graphql_api    |
graphql_api    | sh: 1: npm-run-all: not found
graphql_api    | npm ERR! code ELIFECYCLE
graphql_api    | npm ERR! syscall spawn
graphql_api    | npm ERR! file sh
graphql_api    | npm ERR! errno ENOENT
graphql_api    | npm ERR! my-graphql-app@1.0.0 start: `npm-run-all --parallel build:watch run:watch`
graphql_api    | npm ERR! spawn ENOENT
graphql_api    | npm ERR!
graphql_api    | npm ERR! Failed at the my-graphql-app@1.0.0 start script.
graphql_api    | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

I have also tried building the container while starting from a node:11 image instead of a node:12 image, to match the Node version I have installed locally, but the result is the same.

I am really at a loss here: I have tried changing many things around after googling and looking at other StackOverflow answers (for example, the addition of "private": true in pacakge.json comes from an answer I found here to a similar question) but I still cannot get this container to run.

4 Answers

According to your error message, the package npm-run-all is missing. Inside dockerfile, install this package (globally) before the "npm install" line and try again.

Hope it helps!

You could try adding ./node_modules/.bin/ to your PATH in the dockerfile. That is likely where npm-run-all is located.

If you execute the command from ./graphql_api/node_modules/.bin/ then npm-run-all would work.

Then here you would have two options.

  1. You can export /graphql_api/node_modules/.bin/ to the PATH environment variable in your Dockerfile as follows; ENV PATH="/graphql_api/node_modules/.bin/:${PATH}"
  2. You can install npm-run-all as globally with executing command npm i -g npm-run-all.

Please see this particular issue created that I found while looking into your problem referenced below. https://github.com/mysticatea/npm-run-all/issues/96

The only way is to export /graphql_api/node_modules/.bin/ to the PATH. Location can prevent from those repercussions

Related