Schovi
Schovi

Reputation: 1990

Docker - Override content of linked volume

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?

Upvotes: 3

Views: 1971

Answers (3)

CristoJV
CristoJV

Reputation: 500

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

Upvotes: 1

Schovi
Schovi

Reputation: 1990

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.

Upvotes: 0

nwinkler
nwinkler

Reputation: 54467

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.

Upvotes: 1

Related Questions