development

Docker-compose : npm 설치가 성공한 후 볼륨에 node_modules가 없습니다.

big-blog 2020. 6. 11. 07:43
반응형

Docker-compose : npm 설치가 성공한 후 볼륨에 node_modules가 없습니다.


다음 서비스를 갖춘 앱이 있습니다.

  • web/ -포트 5000에서 Python 3 플라스크 웹 서버를 유지하고 실행합니다. sqlite3을 사용합니다.
  • worker/- index.js큐의 작업자 파일이 있습니다. 웹 서버는 json API over port를 사용하여이 대기열과 상호 작용합니다 9730. 작업자는 스토리지에 redis를 사용합니다. 작업자는 폴더에 로컬로 데이터를 저장합니다worker/images/

이제이 질문은에만 해당 worker됩니다.

worker/Dockerfile

FROM node:0.12

WORKDIR /worker

COPY package.json /worker/
RUN npm install

COPY . /worker/

docker-compose.yml

redis:
    image: redis
worker:
    build: ./worker
    command: npm start
    ports:
        - "9730:9730"
    volumes:
        - worker/:/worker/
    links:
        - redis

내가 실행 docker-compose build하면 모든 것이 예상대로 작동하고 모든 npm 모듈이 예상대로 설치됩니다 /worker/node_modules.

npm WARN package.json unfold@1.0.0 No README data

> phantomjs@1.9.2-6 install /worker/node_modules/pageres/node_modules/screenshot-stream/node_modules/phantom-bridge/node_modules/phantomjs
> node install.js

<snip>

그러나 내가 할 docker-compose up때이 오류가 나타납니다.

worker_1 | Error: Cannot find module 'async'
worker_1 |     at Function.Module._resolveFilename (module.js:336:15)
worker_1 |     at Function.Module._load (module.js:278:25)
worker_1 |     at Module.require (module.js:365:17)
worker_1 |     at require (module.js:384:17)
worker_1 |     at Object.<anonymous> (/worker/index.js:1:75)
worker_1 |     at Module._compile (module.js:460:26)
worker_1 |     at Object.Module._extensions..js (module.js:478:10)
worker_1 |     at Module.load (module.js:355:32)
worker_1 |     at Function.Module._load (module.js:310:12)
worker_1 |     at Function.Module.runMain (module.js:501:10)

/worker/node_modules호스트 또는 컨테이너에 모듈이없는 것으로 나타났습니다 .

호스트 인 경우 npm install모든 것이 잘 작동합니다. 그러나 나는 그것을하고 싶지 않습니다. 컨테이너가 종속성을 처리하기를 원합니다.

무슨 일이야?

말할 필요도없이, 모든 패키지는 안에 package.json있습니다.


이는 빌드 중에 볼륨이 마운트되지 않았기 때문에 worker디렉토리를에 볼륨으로 추가했기 때문에 발생합니다 docker-compose.yml.

docker가 이미지를 빌드하면 node_modules디렉토리가 디렉토리 내에 작성 worker되고 모든 종속성이 설치됩니다. 그런 다음 런타임에 worker외부 도커 디렉토리가 도커 인스턴스 (설치되지 않은)에 마운트되어 방금 설치 node_modulesnode_modules것을 숨 깁니다 . 에서 마운트 된 볼륨을 제거하여이를 확인할 수 있습니다 docker-compose.yml.

해결 방법은 데이터 볼륨을 사용하여 모든을 저장하는 것입니다 node_modules. 데이터 볼륨은 worker디렉토리가 마운트 되기 전에 내장 된 docker 이미지의 데이터에 복사되기 때문 입니다. 이것은 다음 docker-compose.yml과 같이 할 수 있습니다 :

redis:
    image: redis
worker:
    build: ./worker
    command: npm start
    ports:
        - "9730:9730"
    volumes:
        - worker/:/worker/
        - /worker/node_modules
    links:
        - redis

이것이 이미지의 이식성에 문제를 일으키는 지 여부는 확실하지 않지만 런타임 환경을 제공하기 위해 주로 도커를 사용하는 것처럼 보이지만 이것은 문제가되지 않습니다.

볼륨에 대한 자세한 내용을 보려면 https://docs.docker.com/userguide/dockervolumes/ 에서 유용한 사용자 안내서를 참조 하십시오.


node_modules볼륨 폴더를 덮어 쓰고 컨테이너에서 더 이상 액세스 할 수 없습니다. 내가 사용하고 네이티브 모듈 로딩 전략을 볼륨에서 폴더를 꺼내 :

/data/node_modules/ # dependencies installed here
/data/app/ # code base

도커 파일 :

COPY package.json /data/
WORKDIR /data/
RUN npm install
ENV PATH /data/node_modules/.bin:$PATH

COPY . /data/app/
WORKDIR /data/app/

node_modules 이미지에 포함되어 있으므로 컨테이너 외부에서 액세스 할 수 없습니다.


@FrederikNS가 제공하는 솔루션은 작동하지만 node_modules 볼륨의 이름을 명시 적으로 지정하는 것을 선호합니다.

project/docker-compose.yml파일 (docker-compose 버전 1.6 이상) :

version: '2'
services:
  frontend:
    ....
    build: ./worker
    volumes:
      - ./worker:/worker
      - node_modules:/worker/node_modules
    ....
volumes:
  node_modules:

내 파일 구조는 다음과 같습니다

project/
   │── worker/
   │     └─ Dockerfile
   └── docker-compose.yml

project_node_modules응용 프로그램을 시작할 때마다 이름이 지정된 볼륨을 생성 하고 재사용합니다.

docker volume ls모습은 다음과 같습니다.

DRIVER              VOLUME NAME
local               project1_mysql
local               project1_node_modules
local               project2_postgresql
local               project2_node_modules

나는 최근에 비슷한 문제가 있었다. node_modules다른 곳에 설치 하고 NODE_PATH환경 변수를 설정할 수 있습니다 .

예에서 I가 설치 아래 node_modules/install

작업자 / Dockerfile

FROM node:0.12

RUN ["mkdir", "/install"]

ADD ["./package.json", "/install"]
WORKDIR /install
RUN npm install --verbose
ENV NODE_PATH=/install/node_modules

WORKDIR /worker

COPY . /worker/

docker-compose.yml

redis:
    image: redis
worker:
    build: ./worker
    command: npm start
    ports:
        - "9730:9730"
    volumes:
        - worker/:/worker/
    links:
        - redis

우아한 해결책이 있습니다.

전체 디렉토리가 아니라 앱 디렉토리 만 마운트하십시오. 이렇게하면에 문제가 발생하지 않습니다 npm_modules.

예:

  frontend:
    build:
      context: ./ui_frontend
      dockerfile: Dockerfile.dev
    ports:
    - 3000:3000
    volumes:
    - ./ui_frontend/src:/frontend/src

Dockerfile.dev :

FROM node:7.2.0

#Show colors in docker terminal
ENV COMPOSE_HTTP_TIMEOUT=50000
ENV TERM="xterm-256color"

COPY . /frontend
WORKDIR /frontend
RUN npm install update
RUN npm install --global typescript
RUN npm install --global webpack
RUN npm install --global webpack-dev-server
RUN npm install --global karma protractor
RUN npm install
CMD npm run server:dev

UPDATE: Use the solution provided by @FrederikNS.

I encountered the same problem. When the folder /worker is mounted to the container - all of it's content will be syncronized (so the node_modules folder will disappear if you don't have it locally.)

Due to incompatible npm packages based on OS, I could not just install the modules locally - then launch the container, so..

My solution to this, was to wrap the source in a src folder, then link node_modules into that folder, using this index.js file. So, the index.js file is now the starting point of my application.

When I run the container, I mounted the /app/src folder to my local src folder.

So the container folder looks something like this:

/app
  /node_modules
  /src
    /node_modules -> ../node_modules
    /app.js
  /index.js

It is ugly, but it works..


Due to the way Node.js loads modules, node_modules can be anywhere in the path to your source code. For example, put your source at /worker/src and your package.json in /worker, so /worker/node_modules is where they're installed.


Installing node_modules in container to different from project folder, and setting NODE_PATH to your node_modules folder helps me (u need to rebuild container).

I'm using docker-compose. My project file structure:

-/myproject
--docker-compose.yml
--nodejs/
----Dockerfile

docker-compose.yml:

version: '2'
services:
  nodejs:
    image: myproject/nodejs
    build: ./nodejs/.
    volumes:
      - ./nodejs:/workdir
    ports:
      - "23005:3000"
    command: npm run server

Dockerfile in nodejs folder:

FROM node:argon
RUN mkdir /workdir
COPY ./package.json /workdir/.
RUN mkdir /data
RUN ln -s /workdir/package.json /data/.
WORKDIR /data
RUN npm install
ENV NODE_PATH /data/node_modules/
WORKDIR /workdir

There is also some simple solution without mapping node_module directory into another volume. It's about to move installing npm packages into final CMD command.

Disadvantage of this approach:

  • run npm install each time you run container (switching from npm to yarn might also speed up this process a bit).

worker/Dockerfile

FROM node:0.12
WORKDIR /worker
COPY package.json /worker/
COPY . /worker/
CMD /bin/bash -c 'npm install; npm start'

docker-compose.yml

redis:
    image: redis
worker:
    build: ./worker
    ports:
        - "9730:9730"
    volumes:
        - worker/:/worker/
    links:
        - redis

There are two seperate requirements I see for node dev environments... mount your source code INTO the container, and mount the node_modules FROM the container (for your IDE). To accomplish the first, you do the usual mount, but not everything... just the things you need

volumes:
    - worker/src:/worker/src
    - worker/package.json:/worker/package.json
    - etc...

( the reason to not do - /worker/node_modules is because docker-compose will persist that volume between runs, meaning you can diverge from what is actually in the image (defeating the purpose of not just bind mounting from your host)).

The second one is actually harder. My solution is a bit hackish, but it works. I have a script to install the node_modules folder on my host machine, and I just have to remember to call it whenever I update package.json (or, add it to the make target that runs docker-compose build locally).

install_node_modules:
    docker build -t building .
    docker run -v `pwd`/node_modules:/app/node_modules building npm install

In my opinion, we should not RUN npm install in the Dockerfile. Instead, we can start a container using bash to install the dependencies before runing the formal node service

docker run -it -v ./app:/usr/src/app  your_node_image_name  /bin/bash
root@247543a930d6:/usr/src/app# npm install

You can try something like this in your Dockerfile:

FROM node:0.12
WORKDIR /worker
CMD bash ./start.sh

Then you should use the Volume like this:

volumes:
  - worker/:/worker:rw

The startscript should be a part of your worker repository and looks like this:

#!/bin/sh
npm install
npm start

So the node_modules are a part of your worker volume and gets synchronized and the npm scripts are executed when everything is up.

참고URL : https://stackoverflow.com/questions/30043872/docker-compose-node-modules-not-present-in-a-volume-after-npm-install-succeeds

반응형