5

At the top of my react component (Coffee.jsx), I have this import:

import ReactPlayer from 'react-player';

The package 'react-player' is certainly installed, present at package.json and node_modules/.

My code runs inside a docker container. Everytime I spin my containers up, like so:

docker-compose -f docker-compose-dev.yml up -d 

I am getting this error:

./src/components/Coffees.jsx
Module not found: Can't resolve 'react-player' in '/usr/src/app/src/components'

this is what console shows me:

Brewing.jsx:22 Uncaught Error: Cannot find module 'react-player'
    at webpackMissingModule (Brewing.jsx:22)
    at Module../src/components/Coffees.jsx (Brewing.jsx:22)
    at __webpack_require__ (bootstrap:781)
    at fn (bootstrap:149)
    at Module../src/App.jsx (Spotify.css:4)
    at __webpack_require__ (bootstrap:781)
    at fn (bootstrap:149)
    at Module../src/index.js (spotify-auth.js:8)
    at __webpack_require__ (bootstrap:781)
    at fn (bootstrap:149)
    at Object.0 (index.js:10)
    at __webpack_require__ (bootstrap:781)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1

docker-compose-dev.yml:

  client:
    build:
      context: ./services/client
      dockerfile: Dockerfile-dev
    volumes:
      - './services/client:/usr/src/app'
      - '/usr/src/app/node_modules'
    ports:
      - 3000:3000
    environment:
      - NODE_ENV=development
      - REACT_APP_WEB_SERVICE_URL=${REACT_APP_WEB_SERVICE_URL}
    depends_on:
      - web

Dockerfile-dev:

# base image
FROM node:11.12.0-alpine

# set working directory
WORKDIR /usr/src/app

# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH

# install and cache app dependencies
COPY package.json /usr/src/app/package.json
COPY package-lock.json /usr/src/app/package-lock.json
RUN npm ci
RUN npm install [email protected] -g --silent

# start app
CMD ["npm", "start"]

folder structure:

services/
       docker-compose-dev.yml
       node_modules/
       client/
             Dockerfile-dev
             package.json
             package-lock.json
             node_modules/
                         react-player/

Temporay fix:

The hack fixing this is waiting for some time, along with some forced changes in my code either in Coffee.jsx or Brewing.jsx.

After I save the changed code, the package is found.

Then, when I stop containers and up them again, problem resumes. I have trying using the flag --build after up -d, to no avail.

Whats going on? How do I fix this?


more persistent fix:

After removing volumes from docker-compose-dev.yml and rebuilding, like so:

#volumes:
      #- './services/client:/usr/src/app'
      #- '/usr/src/app/node_modules'

I still get the error:

client_1           | > [email protected] start /usr/src/app
client_1           | > react-scripts start
client_1           | 
client_1           | Could not find a required file.
client_1           |   Name: index.html
client_1           |   Searched in: /usr/src/app/public
client_1           | npm ERR! code ELIFECYCLE
client_1           | npm ERR! errno 1
client_1           | npm ERR! [email protected] start: `react-scripts start`
client_1           | npm ERR! Exit status 1
client_1           | npm ERR! 
client_1           | npm ERR! Failed at the [email protected] start script.
client_1           | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
client_1           | 
client_1           | npm ERR! A complete log of this run can be found in:
client_1           | npm ERR!     /root/.npm/_logs/2019-11-05T15_14_42_967Z-debug.log

Then it only works if I uncomment volumes again and run the containers with volumes. An answer explaining reasons for

a) temporary fix b) more permanent fix

would be very appreciated.

2
  • 1
    You tagged this as "docker"; are you running this inside a Docker container? If so, can you add the relevant docker run line or docker-compose.yml file to the question? Commented Oct 29, 2019 at 23:15
  • I sure can. please refer to edit. thank you Commented Oct 30, 2019 at 0:00

3 Answers 3

4
+50

Managing node_modules is such a pain with docker. There are great discussions on the stackoverflow about how you can run Javascrip app with docker. Here is how I do it,

Dockerfile

FROM node:11.12.0-alpine

# first installed node_modules in cache and copy them to src folder
RUN mkdir /usr/src/cache
WORKDIR /usr/src/cache

COPY package.json .
RUN npm install -q

# now make a different directory for src code 
RUN mkdir /usr/src/app
WORKDIR /usr/src/app

# set path to run packages from node_modules
ENV NODE_PATH=/usr/src/app/node_modules/.bin

COPY . .

docker-compose.yaml

app:
    build: .
    image: app
    container_name: services.app
    volumes:
      - .:/usr/src/app
    ports:
      - 3000:5000 
    # this will copy node_modules to src folder, otherwise node_modules will be wipeed out as we don't
    # have the node_modules in the host machine
    command: /usr/src/app/entrypoint.sh prod

And my entrypoint.sh file looks like

#!/bin/bash

cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/

exec npm start

So, the basic idea here is, when you build the image you store the node_modules somewhere in the path, but when you actually run it, you copy that node_modules and place it in the app folder. This way, your local node_modules never clashes with the one in the docker.

You can add node_modules in .dockerignore if you want to make a COPY faster.

Sign up to request clarification or add additional context in comments.

2 Comments

do you see why the module is found after some time and resaving the files at host? I don't understand.
It is really hard to tell without looking at the actual code and inspecting the containers at different times.Helicopter view: volume is miss behaving and the changes on any files mounting the new volume from client and you are seeing all the packages from the node_modules. Suggestion: remove volume using docker volume prune or with -f option if necessary.
1

First Down services:

docker-compose -f docker-compose-dev.yml down

Then re-build services (without cache):

docker-compose -f docker-compose-dev.yml build --no-cache

In the last run services:

docker-compose -f docker-compose-dev.yml up

Comments

1

I will go for installing packages whenever container up it will install on start on stop as well plus if can control mechanism too when to install or when to go with build time modules.

#!/bin/sh
npm ci
npm install [email protected] -g --silent
exec npm start

With this approach the container will always install updated node modules, also will not need to build each time during development.

Also, we can control this behaviour.

#!/bin/sh
if [ "$PACKAGE_UPDATE" = true ] ; then
    echo 'installing fresh node modules'
    # you can also remove existing modules at this step
    npm ci
    npm install [email protected] -g --silent
 fi
exec npm start

so the docker run for not installing packages will be

docker run -e PACKAGE_UPDATE=true -it my_image 

and will mount the anonymous volume to not conflict with host node modules.

    volumes:
      - './services/client:/usr/src/app'
      - '/usr/src/app/node_modules'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.