Unable to create node_modules folder at host and m

2019-04-30 02:09发布

问题:

My dockerfile will run npm install, however after docker-compose build the folder node_modules in my host folder remains empty even after seeing building. How can i get the folder up and reflected in the host too?

This is docker-compose.yml:

This is my docker-compose

version: "2"

volumes: 
  mongostorage:

services:
  app:
    build: ./app
    ports:
      - "3000"
    links:
      - mongo
      - redis
    command: node ./bin/www
  nginx:
    build: ./nginx
    ports:
      - "80:80"
    links:
      - app:app
  mongo:
    image: mongo:latest
    environment:
      - MONGO_DATA_DIR=/data/db
    volumes:
      - mongostorage:/data/db
    ports:
      - "27017:27017"
  redis:
    image: redis
    volumes:
      - ./data/redis/db:/data/db
    ports:
      - "6379:6379"

This is dockerfile in app

FROM node:6.3

RUN mkdir -p /var/www/app

WORKDIR /var/www/app

VOLUME /var/www/app

COPY . /var/www/app    

COPY package.json /var/www/app

RUN npm install

package.json

{
  "name": "app",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "body-parser": "^1.13.3",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "helmet": "^3.0.0",
    "jade": "~1.11.0",
    "redis": "^2.6.2",
    "serve-favicon": "~2.3.0"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^3.1.1",
    "gulp-complexity": "^0.3.2",
    "gulp-concat": "^2.6.1",
    "gulp-cssnano": "^2.1.2",
    "gulp-less": "^3.3.0",
    "gulp-uglify": "^1.5.4",
    "gulp-watch": "^4.3.11",
    "strip-debug": "^1.1.1",
    "util": "^0.10.3"
  }
}

docker logs for the app container returns after docker-compose up error:

module.js:442
    throw err;
    ^

Error: Cannot find module 'dotenv'
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at Module.require (module.js:468:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/var/www/nodeapp/app.js:3:1)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)

回答1:

starting fresh..

The following is, I believe, what you are asking for, but I'm not sure it's what you want.

What is the actual use case you are trying to address?

If it is to be able to develop your app, modifying files on your local system and have them reflected in the docker container this is not the way to do it..

I have used the npm module serve as an easy way to keep the container running.

I have used a named volume to make things easier. The volume data is defined in docker-compose and mounted on /var/www/app.

fyi, you could also try moving the VOLUME instruction in your original Dockerfile to the bottom as at https://docs.docker.com/engine/reference/builder/#volume:

Changing the volume from within the Dockerfile: If any build steps change the data within the volume after it has been declared, those changes will be discarded.

But this still only defines the volume mount point in the container, you still need to mount it on the host at run time.

App files:

$ tree
.
├── app
│   ├── Dockerfile
│   └── package.json
└── docker-compose.yml

1 directory, 3 files

$ cat app/Dockerfile
FROM node:6.3
RUN mkdir -p /var/www/app
WORKDIR /var/www/app
COPY . /var/www/app
RUN npm install

$ cat app/package.json
{
  "name": "app",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "serve"
  },
  "dependencies": {
    "serve": "*"
  }
}

$ cat docker-compose.yml
version: "2"

services:
  app:
    build: ./app
    ports:
      - "3000"
    command: npm start
    volumes:
      - data:/var/www/app
volumes:
  data:

Build the app:

$ docker-compose build app
Building app
Step 1/5 : FROM node:6.3
---> 0d9089853221
Step 2/5 : RUN mkdir -p /var/www/app
---> Using cache
---> 18cc43628367
Step 3/5 : WORKDIR /var/www/app
---> Using cache
---> b8fa2b1a2624
Step 4/5 : COPY . /var/www/app
---> de38a6c3f784
Step 5/5 : RUN npm install
---> Running in 5a035f687de1
npm info it worked if it ends with ok
npm info using npm@3.10.3
npm info using node@v6.3.1
npm info attempt registry request try #1 at 1:19:21 PM
npm http request GET https://registry.npmjs.org/serve
...
npm info ok
---> 76b99c707ac1
Removing intermediate container 5a035f687de1
Successfully built 76b99c707ac1
Successfully tagged 47173020_app:latest

Bring up the app

$ docker-compose up -d app
Recreating 47173020_app_1 ...
Recreating 47173020_app_1 ... done

Check the app logs

$ docker-compose logs app
Attaching to 47173020_app_1
app_1  | npm info it worked if it ends with ok
app_1  | npm info using npm@3.10.3
app_1  | npm info using node@v6.3.1
app_1  | npm info lifecycle app@0.0.0~prestart: app@0.0.0
app_1  | npm info lifecycle app@0.0.0~start: app@0.0.0
app_1  |
app_1  | > app@0.0.0 start /var/www/app
app_1  | > serve
app_1  |
app_1  | serve: Running on port 5000

Now the volume you are looking for on the host is on the docker host running as a vm on your local machine and can only be accessed from a running container.

I have taken the following from Inspecting Docker Volumes on a Mac/Windows the Easy Way which you can refer to for more detail.

List the docker volumes

$ docker volume ls
local               47173020_data

Inspect the volume to get it's mount point

$ docker volume inspect 47173020_data
[
    {
        "CreatedAt": "2017-11-13T13:15:59Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/47173020_data/_data",
        "Name": "47173020_data",
        "Options": {},
        "Scope": "local"
    }
]

Start up a simple container, mount "/docker" on the host root, and list the files in the volume which are the ones copied and created by the Dockerfile

$ docker run --rm -it -v /:/docker alpine:edge ls -l /docker/var/lib/docker/volumes/47173020_data/_data
total 12
-rw-r--r--    1 root     root           119 Nov 13 12:30 Dockerfile
drwxr-xr-x  153 root     root          4096 Nov 13 13:14 node_modules
-rw-r--r--    1 root     root           144 Nov 13 13:03 package.json


回答2:

That VOLUME instruction is mounting your app directory to the host which would be hiding anything you put in there on the container. I'm actually surprised that you see the node_modules directory. You don't need the COPY package.json instruction either as the COPY . should take care of that. Try the following Dockerfile instead..

FROM node:6.3
RUN mkdir -p /var/www/app
WORKDIR /var/www/app
COPY . /var/www/app    
RUN npm install

This works fine for me using the info you have provided. Running docker-compose build from the directory which contains the Dockerfile builds the image successfully.

$ tree
.
├── app
│   ├── Dockerfile
│   └── package.json
└── docker-compose.yml

1 directory, 3 files

$ cat docker-compose.yml
version: "2"
services:
  app:
    build: ./app
    ports:
      - "3000"
    command: node ./bin/www

$ cat app/Dockerfile
FROM node:6.3
RUN mkdir -p /var/www/app
WORKDIR /var/www/app
COPY . /var/www/app
RUN npm install

$ cat app/package.json
{
  "name": "app",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "body-parser": "^1.13.3",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "express": "~4.13.1",
    "helmet": "^3.0.0",
    "jade": "~1.11.0",
    "redis": "^2.6.2",
    "serve-favicon": "~2.3.0"
  },
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^3.1.1",
    "gulp-complexity": "^0.3.2",
    "gulp-concat": "^2.6.1",
    "gulp-cssnano": "^2.1.2",
    "gulp-less": "^3.3.0",
    "gulp-uglify": "^1.5.4",
    "gulp-watch": "^4.3.11",
    "strip-debug": "^1.1.1",
    "util": "^0.10.3"
  }
}

run the build..

$ docker-compose build
Building app
Step 1/5 : FROM node:6.3
6.3: Pulling from library/node
357ea8c3d80b: Pull complete
...
646e6da4bf07: Pull complete
Digest: sha256:cde2bd38dbfec5e6e2981ec7a05056c734148fcd4bff088e143f11b2bafe3b64
Status: Downloaded newer image for node:6.3
---> 0d9089853221
Step 2/5 : RUN mkdir -p /var/www/app
---> Running in 018dd9b28c57
---> 18cc43628367
Removing intermediate container 018dd9b28c57
Step 3/5 : WORKDIR /var/www/app
---> b8fa2b1a2624
Removing intermediate container ba1ad506cab2
Step 4/5 : COPY . /var/www/app
---> 3f37c76acdc4
Step 5/5 : RUN npm install
---> Running in dd87c26c2546
npm info it worked if it ends with ok
npm info using npm@3.10.3
npm info using node@v6.3.1
npm info attempt registry request try #1 at 11:39:41 AM
npm http request GET https://registry.npmjs.org/body-parser
...
npm info lifecycle util@0.10.3~postinstall: util@0.10.3
npm info lifecycle app@0.0.0~preinstall: app@0.0.0
npm info linkStuff app@0.0.0
npm info lifecycle app@0.0.0~install: app@0.0.0
npm info lifecycle app@0.0.0~postinstall: app@0.0.0
npm info lifecycle app@0.0.0~prepublish: app@0.0.0
app@0.0.0 /var/www/app
+-- body-parser@1.18.2
| +-- bytes@3.0.0
...
npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.1.2
npm info ok
---> d1bfc665f54c
Removing intermediate container dd87c26c2546
Successfully built d1bfc665f54c
Successfully tagged so47173020_app:latest

modifying the Dockerfile command as done below I am able to run docker-compose up app and see all the modules installed in the node_modules directory.

version: "2"
services:
  app:
    build: ./app
    ports:
      - "3000"
    command: ls -la node_modules

output of docker-compose up app:

Creating so47173020_app_1 ...
Creating so47173020_app_1 ... done
Attaching to so47173020_app_1
app_1  | total 2004
app_1  | drwxr-xr-x 497 root root 20480 Nov 10 11:40 .
app_1  | drwxr-xr-x   1 root root  4096 Nov 10 11:40 ..
app_1  | drwxr-xr-x   2 root root  4096 Nov 10 11:40 .bin
app_1  | drwxr-xr-x   2 root root  4096 Nov 10 11:40 accepts
app_1  | drwxr-xr-x   4 root root  4096 Nov 10 11:40 accord
...
app_1  | drwxr-xr-x   3 root root  4096 Nov 10 11:40 x-xss-protection
app_1  | drwxr-xr-x   2 root root  4096 Nov 10 11:40 xtend
app_1  | drwxr-xr-x   3 root root  4096 Nov 10 11:40 yargs
so47173020_app_1 exited with code 0