5

I am new to Docker. I have a project set up something like this:

app/
dist/
node_modules/       
package.json
Dockerfile           
docker-compose.yml  
.dockerignore        

Dockerfile

FROM node:10.16.2

WORKDIR /app

RUN sed -i '/jessie-updates/d' /etc/apt/sources.list

RUN apt-get update
RUN rm -rf /var/lib/apt/lists/*
RUN npm install --quiet
RUN npm install -g gulp

EXPOSE 3000

docker-compose.yml

version: '2'

services:
  web:
    build: .
    command: gulp
    ports:
      - "3000:3000"
    volumes:
      - .:/app
  package:
    build: .
    command: ./package.sh
    volumes:
      - ./package:/app/package

.dockerignore

# add git-ignore syntax here of things you don't want copied into docker image

.git
*Dockerfile*
*docker-compose*
package-lock.json
node_modules/

When I run docker-compose build --no-cache web && docker-compose up web, it is actually not creating it's own node_modules but using the local system's. I want docker's own node_modules when I run docker. Please help.

I do understand, I am copying all files from local to docker setup, but I want to exclude node_modules and also make it install its own node_modules.

Mr_Green
  • 40,727
  • 45
  • 159
  • 271
  • 3
    I do not see any COPY or ADD statements in your dockerfile. You should be copying the sources if you want to run the npm install there. Ideally for a single page application you do not need the node_modules to be present. You should be building the optimized distribution and add only that to the container. – Mohit Mutha Aug 19 '19 at 06:03
  • 1
    I don't want to COPY the files if I understand correctly. There is a chance that I change these files.. I want to watch these files in docker i.e the docker should use my local volume except the node_modules. – Mr_Green Aug 19 '19 at 08:04
  • 1
    Volumes are mounted at run time from your docker-compose whereas the docker build will be done before that. The npm install commands will run on the files available during the build – Mohit Mutha Aug 19 '19 at 08:46
  • What are the contents of the `.dockerignore` file? – BMitch Aug 21 '19 at 18:34
  • @BMitch updated with .dockerignore file. please check. – Mr_Green Aug 22 '19 at 06:41
  • Most of my node.js app Dockerfiles have `WORKDIR /app` then `COPY package.json .` followed by a `RUN npm install` to build the node_modules folder. Then it finishes up with a `COPY . .` to copy the remaining source code and files for the app. Yours doesn't have any COPY commands whatsoever, so I'm really confused as to what you're trying to do. – Wyck Aug 23 '19 at 18:25

4 Answers4

1

You're mounting a host volume, that is your project folder into your container by doing

volumes:
      - .:/app

So, when you do something like WORKDIR /app, you're mapping the working directory where your Dockerfile is to /app in your container, so you're actually in your project folder on the host, not a copy. You're running npm install on the host again. If you modify anything inside that folder (app), the changes will be written directly to the host.

.dockerignore has no effect here. When you build an image, Docker will copy the content of the working directory where the Dockerfile exists (the build context) inside the image. That's an automatic process, you don't have to do it YOURSELF. So that's why you would use .dockerignore, so that you can exclude files and directories from being copied during the build process.

You mount volumes when you have data on your host that you would like to make available in a container (read/write access - it's configurable, appending :ro will make it read-only). Be aware that volumes are applied to containers at runtime. .dockerignore is just used when building the image. More on volumes.

jperl
  • 4,662
  • 2
  • 16
  • 29
0

The problem is your volume mount within the docker-compose.yml. However, this same problem has been adressed in this question.

You can manually override just the node_modules in your volume by doing this:

volumes:
    - '.:/app'
    - /app/node_modules/

This way, the node_modules should be empty.

Edit:

This approach seems not to be working anymore. Instead, create an empty folder on your machine, e.g. empty.d and mount this directory:

volumes:
    - '.:/app'
    - 'empty.d/:/app/node_modules/'

However, as your container name is build, maybe you should consider dropping the volume and instead COPY or ADD your directory in the Dockerfile.

alex kucksdorf
  • 2,573
  • 1
  • 15
  • 26
  • HI, I am getting error `npm WARN saveError ENOENT: no such file or directory, open '/app/package.json'` and other errors too. – Mr_Green Aug 19 '19 at 08:02
0

node_modules will be generated when you install an NPM module. the only module that you're installing is gulp but with the global option -g so the module will not be installed in the current directory.

try installing your modules locally for example by adding this line to you Dockerfile

RUN npm install fs

and you'll see that the node_modules folder is created.

Bouzid Zitouni
  • 1,119
  • 8
  • 12
0

You mount project root dir to "/app" path in the container with volume in compose file. Because of that, when you start your container, your local node_modules replace itself in container's volume path(container's node_modules folder). You must isolate node_modules from the volume in docker-compose.yml file. And I guess you have a gulpfile.js in the project folder. I add this for you.

Dockerfile

FROM node:10.16.2

WORKDIR /home

RUN sed -i '/jessie-updates/d' /etc/apt/sources.list

RUN apt-get update
RUN rm -rf /var/lib/apt/lists/*
RUN npm install --quiet
RUN npm install -g gulp

EXPOSE 3000

docker-compose.yml

version: '2'

services:
  web:
    build: .
    command: gulp
    ports:
      - "3000:3000"
    volumes:
      - ./app:/home/app
      - ./dist:/home/dist
      - ./package.json:/home/package.json
      - ./gulpfile.js:/home/gulpfile.js
  package:
    build: .
    command: ./package.sh
    volumes:
      - ./package:/home/package

With this configuration, when you install a new node package, you must install it for each services. You can do this with "docker exec [container_id] npm install".

I hope, you will be happy with this post :)

Emircan Ok
  • 320
  • 2
  • 13