J'ai le problème d'installer node_modules
Dans le conteneur Docker et de les synchroniser avec l'hôte. La version de mon Docker est 18.03.1-ce, build 9ee9f40
Et celle de Docker Compose est 1.21.2, build a133471
.
Mon docker-compose.yml
Ressemble à ceci:
# Frontend Container.
frontend:
build: ./app/frontend
volumes:
- ./app/frontend:/usr/src/app
- frontend-node-modules:/usr/src/app/node_modules
ports:
- 3000:3000
environment:
NODE_ENV: ${ENV}
command: npm start
# Define all the external volumes.
volumes:
frontend-node-modules: ~
Mon Dockerfile
:
# Set the base image.
FROM node:10
# Create and define the working directory.
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
# Install the application's dependencies.
COPY package.json ./
COPY package-lock.json ./
RUN npm install
L'astuce avec le volume externe est décrite dans de nombreux articles de blog et réponses Stack Overflow. Par exemple, celui-ci .
L'application fonctionne très bien. Le code source est synchronisé. Le rechargement à chaud fonctionne également très bien.
Le seul problème que j'ai est que le dossier node_modules
Est vide sur l'hôte. Est-il possible de synchroniser le dossier node_modules
Qui se trouve dans le conteneur Docker avec l'hôte?
J'ai déjà lu ces réponses:
Malheureusement, ils ne m'ont pas beaucoup aidé. Je n'aime pas le premier , car je ne souhaite pas exécuter npm install
Sur mon hôte à cause des problèmes multi-plateformes possibles (par exemple, l'hôte est Windows ou Mac et le conteneur Docker est Debian 8 ou Ubuntu 16.04). Le second n'est pas bon pour moi aussi, parce que j'aimerais exécuter npm install
Dans mon Dockerfile
au lieu de l'exécuter après le démarrage du conteneur Docker.
En outre, j'ai trouvé cet article de blog . L'auteur tente de résoudre le même problème auquel je suis confronté. Le problème est que node_modules
Ne sera pas synchronisé car nous les copions simplement du conteneur Docker vers l'hôte.
J'aimerais que mon node_modules
À l'intérieur du conteneur Docker soit synchronisé avec l'hôte. S'il vous plaît, prenez en compte que je veux:
node_modules
automatiquement au lieu de manuellementnode_modules
dans le conteneur Docker à la place de l'hôtenode_modules
soit synchronisé avec l'hôte (si j'installe un nouveau package dans le conteneur Docker, il doit être synchronisé automatiquement avec l'hôte, sans aucune action manuelle)J'ai besoin de node_modules
Sur l'hôte, car:
node_modules
pour être installé localement afin de pouvoir accéder au devDependencies
tel que eslint
ou prettier
. Je ne veux pas installer ces devDependencies
globalement.Merci d'avance.
Au début, je voudrais remercier David Maze et trust512 pour avoir posté leurs réponses. Malheureusement, ils ne m'ont pas aidé à résoudre mon problème.
Je voudrais poster ma réponse à cette question.
Mon docker-compose.yml
:
---
# Define Docker Compose version.
version: "3"
# Define all the containers.
services:
# Frontend Container.
frontend:
build: ./app/frontend
volumes:
- ./app/frontend:/usr/src/app
ports:
- 3000:3000
environment:
NODE_ENV: development
command: /usr/src/app/entrypoint.sh
Mon Dockerfile
:
# Set the base image.
FROM node:10
# Create and define the node_modules's cache directory.
RUN mkdir /usr/src/cache
WORKDIR /usr/src/cache
# Install the application's dependencies into the node_modules's cache directory.
COPY package.json ./
COPY package-lock.json ./
RUN npm install
# Create and define the application's working directory.
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
Et le dernier mais non le moindre entrypoint.sh
:
#!/bin/bash
cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/
exec npm start
La partie la plus délicate ici consiste à installer le node_modules
Dans le répertoire de cache de node_module
(/usr/src/cache
) Défini dans notre Dockerfile
. Après cela, entrypoint.sh
Déplacera le node_modules
Du répertoire de cache (/usr/src/cache
) Vers notre répertoire d'application (/usr/src/app
). Grâce à cela, tout le répertoire node_modules
Apparaîtra sur notre ordinateur hôte.
En regardant ma question ci-dessus je voulais:
- installer
node_modules
automatiquement au lieu de manuellement- installer
node_modules
dans le conteneur Docker à la place de l'hôte- pour que
node_modules
soit synchronisé avec l'hôte (si j'installe un nouveau package dans le conteneur Docker, il doit être synchronisé automatiquement avec l'hôte, sans aucune action manuelle.
La première chose est faite: node_modules
Sont installés automatiquement. La deuxième chose est faite aussi: node_modules
Sont installés à l'intérieur du conteneur Docker (donc, il n'y aura pas de problèmes multi-plateformes). Et la troisième chose est faite aussi: node_modules
Qui ont été installés à l'intérieur du conteneur Docker seront visibles sur notre ordinateur hôte et ils seront synchronisé ! Si nous installons un nouveau package dans le conteneur Docker, il sera immédiatement synchronisé avec notre ordinateur hôte.
La chose importante à noter: à vrai dire, le nouveau paquet installé dans le conteneur Docker apparaîtra dans /usr/src/app/node_modules
. Comme ce répertoire est synchronisé avec notre ordinateur hôte, ce nouveau package apparaîtra également dans le répertoire node_modules
De notre ordinateur hôte. Mais le /usr/src/cache/node_modules
Aura l'ancienne construction à ce stade (sans ce nouveau paquet). Quoi qu'il en soit, ce n'est pas un problème pour nous. Au cours de la prochaine opération docker-compose up --build
(--build
Est requis), Docker réinstallera le node_modules
(Car package.json
A été modifié) et le entrypoint.sh
Le fichier les déplacera dans notre /usr/src/app/node_modules
.
Vous devriez prendre en compte une autre chose importante. Si vous git pull
Le code du référentiel distant ou git checkout your-teammate-branch
Lorsque Docker est en cours d'exécution, de nouveaux packages peuvent être ajoutés au fichier package.json
. Dans ce cas, vous devez arrêter Docker avec CTRL + C
Et le relancer avec docker-compose up --build
(--build
Est requis). Si vos conteneurs fonctionnent en tant que démon, vous devez simplement exécuter docker-compose stop
Pour arrêter les conteneurs et le relancer avec docker-compose up --build
(--build
Est requis).
Si vous avez des questions, s'il vous plaît laissez-moi savoir dans les commentaires.
J'espère que cela t'aides.
Il y a trois choses qui se passent ici:
docker build
Ou docker-compose build
, Votre fichier Dockerfile crée une nouvelle image contenant un répertoire /usr/src/app/node_modules
Et une installation Node, mais rien d'autre. En particulier, votre application ne figure pas dans l'image construite.docker-compose up
, La directive volumes: ['./app/frontend:/usr/src/app']
Masque tout ce qui se trouvait dans /usr/src/app
Et monte le contenu du système hôte par dessus.volumes: ['frontend-node-modules:/usr/src/app/node_modules']
Monte le volume nommé au-dessus de l’arborescence node_modules
, En masquant le répertoire du système hôte correspondant.Si vous deviez lancer un autre conteneur et y attacher le volume nommé, vous vous attendriez à voir l'arborescence node_modules
. Pour ce que vous décrivez, vous ne voulez simplement pas le volume nommé: supprimez la deuxième ligne du bloc volumes:
Et de la section volumes:
À la fin du fichier docker-compose.yml
.
Je sais que cela a été résolu, mais qu'en est-il:
Dockerfile:
FROM node
# Create app directory
WORKDIR /usr/src/app
# Your other staffs
EXPOSE 3000
docker-composer.yml:
version: '3.2'
services:
api:
build: ./path/to/folder/with/a/dockerfile
volumes:
- "./volumes/app:/usr/src/app"
command: "npm start"
volumes/app/package.json
{
... ,
"scripts": {
"start": "npm install && node server.js"
},
"dependencies": {
....
}
}
Après exécution, node_modules sera présent dans vos volumes, mais son contenu est généré dans le conteneur afin d'éviter tout problème de multiplateforme.
Je ne suggérerais pas que des volumes se chevauchent, bien que je n'ai jamais vu de documents officiels l'interdire, j'ai déjà eu des problèmes avec cela par le passé. Comment je le fais est:
Ce qui précède peut être obtenu en raccourcissant un peu votre fichier de composition:
frontend:
build: ./app/frontend
volumes:
- ./app/frontend:/usr/src/app
ports:
- 3000:3000
environment:
NODE_ENV: ${ENV}
command: npm start
Cela signifie que vous aurez peut-être besoin de deux fichiers Dockerfiles: un pour le développement local et un pour le déploiement d'une image grasse avec tous les fichiers dist de l'application superposés.
Cela dit, considérons un développement Dockerfile:
FROM node:10
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN npm install
Ce qui précède permet à l'application de créer une installation complète de node_modules et de la mapper sur votre emplacement hôte, tandis que la commande spécifiée par docker composerait le démarrage de votre application.
Personne n'a mentionné de solution avec l'utilisation de la fonctionnalité entrypoint
de docker.
Voici ma solution de travail:
Dockerfile (construction à plusieurs étages, donc production et développement local prêt):
FROM node:10.15.3 as production
WORKDIR /app
COPY package*.json ./
RUN npm install && npm install --only=dev
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
FROM production as dev
COPY docker/dev-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["dev-entrypoint.sh"]
CMD ["npm", "run", "watch"]
docker/dev-entrypoint.sh:
#!/bin/sh
set -e
npm install && npm install --only=dev ## Note this line, rest is copy+paste from original entrypoint
if [ "${1#-}" != "${1}" ] || [ -z "$(command -v "${1}")" ]; then
set -- node "$@"
fi
exec "$@"
docker-compose.yml:
version: "3.7"
services:
web:
build:
target: dev
context: .
volumes:
- .:/app:delegated
ports:
- "3000:3000"
restart: always
environment:
NODE_ENV: dev
Avec cette approche, vous atteignez les 3 points que vous souhaitez et à mon humble avis, c’est beaucoup plus propre - il n’est pas nécessaire de déplacer des fichiers.
Merci Vladyslav Turak pour la réponse avec entrypoint.sh
où on copie node_modules
de conteneur à hôte.
J'ai mis en œuvre la même chose, mais je rencontre le problème avec les packages husky, @commitlint, tslint npm.
Je ne peux rien insérer dans le référentiel.
Raison: j'ai copié node_modules
de Linux à Windows. Dans mon cas, moins de 5% des fichiers sont différents (.bin et la plupart des fichiers package.json) et 95% sont identiques. exemple: image avec diff
Je suis donc retourné à la solution avec npm install
de node_modules
pour Windows d’abord (pour IDE et débogage). Et l’image Docker contiendra la version Linux de node_modules
.
Associer votre dossier Host node_modules à votre conteneur node_modules n'est pas une bonne pratique, comme vous le mentionnez. J'ai souvent vu la solution consistant à créer un volume interne pour ce dossier. Ne pas le faire va causer des problèmes pendant la phase de construction.
J'ai rencontré ce problème lorsque j'essayais de créer un environnement de développement de menu fixe pour une angular), qui affiche des erreurs tslib lorsque j'édiais les fichiers de mon dossier Host car le dossier node_modules de mon hôte était vide. (comme prévu).
La solution peu coûteuse qui m'aidait, dans ce cas, était d'utiliser l'extension de code Visual Studio appelée "Conteneurs distants" .
Cette extension vous permettra d’attacher votre code Visual Studio à votre conteneur et d’éditer de manière transparente vos fichiers dans vos dossiers de conteneurs. Pour ce faire, il installera un serveur vscode interne dans votre conteneur de développement. Pour plus d'informations, consultez ce lien .
Assurez-vous cependant que vos volumes sont toujours créés dans votre fichier docker-compose.yml.
J'espère que ça aide: D!