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_modules
한 node_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 fromnpm
toyarn
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.
'development' 카테고리의 다른 글
MySQL에서이 연산자 <=>는 무엇입니까? (0) | 2020.06.11 |
---|---|
CodeIgniter activerecord, 마지막 삽입 ID를 검색 하시겠습니까? (0) | 2020.06.11 |
NSString이 다른 특정 문자열로 시작하는지 확인하는 방법은 무엇입니까? (0) | 2020.06.11 |
jar 이슈의 maven 최종 이름 제어 (0) | 2020.06.11 |
파일이 존재하는 경우에만 Ant 대상을 실행하는 Ant 태스크? (0) | 2020.06.11 |