3

Having simple Node.js docker container

docker-compose.yml:

app:
  build: ./dockerfiles/app
  volumes:
    - /Users/home/work/app:/usr/app

Dockerfile:

FROM node:6.7-slim

COPY package.json /tmp
RUN cd /tmp && npm install

RUN mkdir -p /usr/app
WORKDIR /usr/app

CMD ["node", "./src/app.js"]

What I want to achieve is container where I have package.json and installed node modules (npm install). Part where I copy package.json and install modules inside container is pretty straighforward, but problem occur, when I want to use these node_modules inside linked app. I can't find any way, how to copy /tmp/node_modules into /usr/app/node_modules

Is there any Docker way ho to do that? If not, can I tell my node app to look for node_modules somewhere else than in root directory?

Schovi
  • 1,960
  • 5
  • 19
  • 33
  • use a volume https://docs.docker.com/engine/tutorials/dockervolumes/ or `docker cp` https://docker.github.io/engine/reference/commandline/cp/ or COPY in your Dockerfile in case I have misunderstood – user2915097 Oct 10 '16 at 12:48
  • /usr/app is linked via volumes, but it is happening when I start container. Then I need docker to overwrite /usr/app/node_modules with content from /tmp/node_modules – Schovi Oct 10 '16 at 12:51
  • @nwinkler's answer would do, though I am still trying to understand why are you mounting node_modules if your container always has the updated one? Other container using it as well? – Griffin Oct 10 '16 at 15:34
  • Please also check here for an option for changing the node install directory: http://stackoverflow.com/questions/14742553/npm-local-install-package-to-custom-location – nwinkler Oct 10 '16 at 15:55

3 Answers3

1

You can achieve what you want by changing the CMD used when starting the container, either in your Dockerfile, or in the docker-compose.yml file.

Instead of just starting node ./src/app.js, you want to do two things:

  1. Copy the node_modules over.
  2. Start Node

Using the docker-compose.yml, I would do the following:

app:
  build: ./dockerfiles/app
  volumes:
    - /Users/home/work/app:/usr/app
command: >
  bash -c "

  rm -rf /usr/app/node_modules
  && cp -R /tmp/node_modules /usr/app/node_modules
  && node ./src/app.js
  "

This will delete the existing node modules on the mapped-in volume, then copy in the ones from container, and then finally starts the node app. This is going to happen every time the container is started.

nwinkler
  • 52,665
  • 21
  • 154
  • 168
1

As @schovi has mentioned in order to not override the contents of node_modules within the container and the contents of node_modules within the folder of the host machine, it is necessary to create another internal volume in the docker-compose.yml file:

volumes:
  - ${APP_PATH}:/usr/app
  - /usr/app/node_modules

Doing that makes it safe to copy the files from /tmp/node_modules into /usr/app/node_modules using this instructions.

FROM node

# Node modules
COPY *.json /tmp/
RUN cd /tmp && yarn

# App
RUN mkdir -p /usr/app
WORKDIR /usr/app
RUN cp -a /tmp/node_modules /usr/app/node_modules
ENV NODE_ENV docker

CMD ["run-node", "src/app.js"]

However, I would create first the app folder and install node_modules directly on it, reducing considerably the cache layers and increasing the building speed.

FROM node:12.8.1 #always mind the version

# Node modules
RUN mkdir -p /usr/app
WORKDIR /usr/app

#Mind that point (workdir)
COPY package*.json .
RUN yarn
ENV NODE_ENV docker

CMD ["run-node", "src/app.js"]

I hope it helps! :D

CristoJV
  • 490
  • 6
  • 15
0

Thing that helped me is following usage of volumes

volumes:
  - ${APP_PATH}:/usr/app
  # Empty node_modules directory
  - /usr/app/node_modules

Then in Dockerfile:

FROM node

# Node modules
COPY *.json /tmp/
RUN cd /tmp && yarn
ENV NODE_PATH /tmp/node_modules:${NODE_PATH}

# App
RUN mkdir -p /usr/app
WORKDIR /usr/app
ENV NODE_ENV docker

CMD ["run-node", "src/app.js"]

This allow me to have node_modules in another directory and app will look for them there.

Schovi
  • 1,960
  • 5
  • 19
  • 33