J'ai une application avec les services suivants:
web/
- contient et exécute un serveur Web flask python 3 sur le port 5000. Utilise sqlite3.worker/
- a unindex.js
fichier qui est un ouvrier pour une file d'attente. le serveur Web interagit avec cette file d'attente à l'aide d'une API json sur le port9730
. Le travailleur utilise redis pour le stockage. Le travailleur stocke également les données localement dans le dossierworker/images/
Or cette question ne concerne que le 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
Quand je cours docker-compose build
, tout fonctionne comme prévu et tous les modules npm sont installés /worker/node_modules
comme je m'y attendais.
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>
Mais quand je le fais docker-compose up
, je vois cette erreur:
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)
Il s'avère qu'aucun des modules n'est présent dans /worker/node_modules
(sur l'hôte ou dans le conteneur).
Si sur l'hôte, je npm install
, alors tout fonctionne très bien. Mais je ne veux pas faire ça. Je veux que le conteneur gère les dépendances.
Qu'est-ce qui ne va pas ici?
(Inutile de dire que tous les packages sont inclus package.json
.)
volumes: - worker/:/worker/
bloc dudocker-compose.yml
fichier. Cette ligne écrase le dossier que vous créez avec la commande COPY.When I run docker-compose build, everything works as expected and all npm modules are installed in /worker/node_modules as I'd expect.
- Comment avez-vous vérifié cela?Réponses:
Cela se produit parce que vous avez ajouté votre
worker
répertoire en tant que volume à votredocker-compose.yml
, car le volume n'est pas monté pendant la construction.Lorsque docker crée l'image, le
node_modules
répertoire est créé dans leworker
répertoire et toutes les dépendances y sont installées. Ensuite, lors de l'exécution, leworker
répertoire de l'extérieur du docker est monté dans l'instance de docker (qui n'a pas installénode_modules
), masquant le fichier quenode_modules
vous venez d'installer. Vous pouvez le vérifier en supprimant le volume monté de votredocker-compose.yml
.Une solution de contournement consiste à utiliser un volume de données pour stocker tous les
node_modules
, car les volumes de données sont copiés dans les données de l'image Docker générée avant leworker
montage du répertoire. Cela peut être fait de la manièredocker-compose.yml
suivante:Je ne suis pas tout à fait certain que cela pose des problèmes pour la portabilité de l'image, mais comme il semble que vous utilisez principalement docker pour fournir un environnement d'exécution, cela ne devrait pas être un problème.
Si vous souhaitez en savoir plus sur les volumes, il y a un joli guide de l'utilisateur disponible ici: https://docs.docker.com/userguide/dockervolumes/
EDIT: Docker a depuis changé sa syntaxe pour exiger un
./
début pour le montage dans les fichiers par rapport au fichier docker-compose.yml.la source
/worker/node_modules
resté le même qu'avant (avec les anciennes dépendances). Existe-t-il une astuce pour utiliser un nouveau volume lors de la reconstruction de l'image?docker-compose rm
semble résoudre ce problème, mais je pense qu'il doit y avoir une solution meilleure et plus simple.rebuild --no-cache
chaque fois que les déps changent?Le
node_modules
dossier est écrasé par le volume et n'est plus accessible dans le conteneur. J'utilise la stratégie de chargement du module natif pour retirer le dossier du volume:Dockerfile:
Le
node_modules
répertoire n'est pas accessible depuis l'extérieur du conteneur car il est inclus dans l'image.la source
node_modules
n'est pas accessible de l'extérieur du conteneur mais pas vraiment un inconvénient;)docker-compose run app npm install
vous allez créer un node_modules dans le répertoire courant et vous n'avez plus besoin de reconstruire l'image.La solution fournie par @FrederikNS fonctionne, mais je préfère nommer explicitement mon volume node_modules.
Mon
project/docker-compose.yml
fichier (docker-compose version 1.6+):ma structure de fichiers est:
Il crée un volume nommé
project_node_modules
et le réutilise à chaque fois que j'utilise mon application.Mon
docker volume ls
ressemble à ceci:la source
J'ai récemment eu un problème similaire. Vous pouvez installer
node_modules
ailleurs et définir laNODE_PATH
variable d'environnement.Dans l'exemple ci-dessous, j'ai installé
node_modules
dans/install
worker / Dockerfile
docker-compose.yml
la source
node_modules
basé sur cet article . Mais cela m'a amené à faire l'expérience de ce problème . Cette solution ici de création d'un répertoire séparé pour copier votrepackage.json
, exécutez-npm install
y, puis spécifiez laNODE_PATH
variable d'environnementdocker-compose.yml
pour pointer vers lenode_modules
dossier de ce répertoire fonctionne et semble juste.npm install
sur l'hôte? Il semblenode_modules
apparaître sur l'hôte et être reflété dans le conteneur, en prenant la priorité surNODE_PATH
. Ainsi, le conteneur utilisera node_modules de l'hôte.Il existe une solution élégante:
Ne montez pas tout le répertoire, mais uniquement le répertoire de l'application. De cette façon, vous n'aurez aucun problème avec
npm_modules
.Exemple:
Dockerfile.dev:
la source
MISE À JOUR: utilisez la solution fournie par @FrederikNS.
J'ai rencontré le même problème. Lorsque le dossier
/worker
est monté sur le conteneur - tout son contenu sera synchronisé (ainsi le dossier node_modules disparaîtra si vous ne l'avez pas localement.)En raison de packages npm incompatibles basés sur le système d'exploitation, je ne pouvais pas simplement installer les modules localement - puis lancer le conteneur, donc ..
Ma solution à cela consistait à envelopper la source dans un
src
dossier, puisnode_modules
à créer un lien dans ce dossier, en utilisant ce fichier index.js . Donc, leindex.js
fichier est maintenant le point de départ de mon application.Lorsque j'exécute le conteneur, j'ai monté le
/app/src
dossier dans monsrc
dossier local .Le dossier du conteneur ressemble donc à ceci:
C'est moche , mais ça marche.
la source
En raison de la façon dont Node.js charge les modules , il
node_modules
peut se trouver n'importe où dans le chemin de votre code source. Par exemple, placez votre source à/worker/src
et votrepackage.json
dans/worker
, c'est/worker/node_modules
là où ils sont installés.la source
L'installation de node_modules dans un conteneur à un autre que le dossier du projet et la définition de NODE_PATH dans votre dossier node_modules m'aide (vous devez reconstruire le conteneur).
J'utilise docker-compose. Ma structure de fichiers de projet:
docker-compose.yml:
Dockerfile dans le dossier nodejs:
la source
NODE_PATH
était la clé pour moi.CMD npm start
n'utilise pas le NODE_PATH spécifié.Il existe également une solution simple sans mappage de
node_module
répertoire dans un autre volume. Il est sur le point de déplacer l'installation des packages npm dans la commande CMD finale.worker / Dockerfile
docker-compose.yml
la source
Il y a deux exigences distinctes que je vois pour les environnements de développement de nœuds ... montez votre code source DANS le conteneur et montez les node_modules À PARTIR du conteneur (pour votre IDE). Pour accomplir le premier, vous faites le montage habituel, mais pas tout ... juste ce dont vous avez besoin
(la raison de ne pas faire
- /worker/node_modules
est que docker-compose conservera ce volume entre les exécutions, ce qui signifie que vous pouvez diverger de ce qui est réellement dans l'image (ce qui va à l'encontre de l'objectif de ne pas simplement lier le montage de votre hôte)).Le second est en fait plus difficile. Ma solution est un peu hackish, mais ça marche. J'ai un script pour installer le dossier node_modules sur ma machine hôte, et je dois juste me rappeler de l'appeler chaque fois que je mets à jour package.json (ou l'ajouter à la cible make qui exécute docker-compose build localement).
la source
À mon avis, nous ne devrions pas
RUN npm install
dans le Dockerfile. Au lieu de cela, nous pouvons démarrer un conteneur en utilisant bash pour installer les dépendances avant d'exécuter le service de nœud formella source
node_modules
rester persistant même après la suppression du conteneur, vous devez également savoir quand ou quand ne pas le fairenpm install
manuellement. OP suggère de le faire sur chaque construction d'image . Vous pouvez le faire, mais vous n'avez pas besoin d'utiliser également un volume pour cela. Sur chaque build, les modules seront à jour de toute façon.Vous pouvez essayer quelque chose comme ça dans votre Dockerfile:
Ensuite, vous devez utiliser le volume comme ceci:
Le startscript doit faire partie de votre référentiel de travail et ressemble à ceci:
Ainsi, les node_modules font partie de votre volume de travail et sont synchronisés et les scripts npm sont exécutés lorsque tout est en place.
la source
Vous pouvez également abandonner votre Dockerfile, en raison de sa simplicité, utilisez simplement une image de base et spécifiez la commande dans votre fichier de composition:
C'est particulièrement utile pour moi, car j'ai juste besoin de l'environnement de l'image, mais j'opère sur mes fichiers en dehors du conteneur et je pense que c'est ce que tu veux faire aussi.
la source