Comment installer NVM dans Docker?

101

Je suis en train de créer une nouvelle image Docker et je cherche à installer NVM afin de pouvoir gérer nodejs.

En lisant la documentation sur l'installation de NVM, ils mentionnent que vous devez vous procurer votre fichier .bashrc pour commencer à utiliser NVM.

J'ai essayé de configurer cela dans un Dockerfile, mais jusqu'à présent, la construction échoue avec l'erreur:

"bash: nvm: commande non trouvée"

Voici les lignes pertinentes de mon Dockerfile:

ADD files/nvm_install.sh /root/
RUN chmod a+x  /root/nvm_install.sh
RUN bash -c "/root/nvm_install.sh"
RUN bash -l -c "source /root/.bashrc"
RUN cd /root
RUN bash -l -c "nvm install 0.10.31"

Voici le résultat de la tentative de construction:

docker build -t nginx_dock.

Step 0 : FROM ubuntu
---> 826544226fdc
Step 1 : MAINTAINER dficociello
---> Using cache
---> da3bc340fbb3
Step 2 : RUN apt-get update
---> Using cache
---> 6b6b611feb4f
Step 3 : RUN apt-get install nginx curl -y
---> Using cache
---> 159eb0b16d23
Step 4 : RUN touch /root/.bashrc
---> Using cache
---> 5e9e8216191b
Step 5 : ADD files/nginx.conf /etc/nginx/
---> Using cache
---> c4a4a11296a2
Step 6 : ADD files/nvm_install.sh /root/
---> Using cache
---> b37cba2a18ca
Step 7 : RUN chmod a+x  /root/nvm_install.sh
---> Using cache
---> bb13e2a2893d
Step 8 : RUN bash -c "/root/nvm_install.sh"
---> Using cache
---> 149b49a8fc71
Step 9 : RUN bash -l -c "source /root/.bashrc"
---> Running in 75f353ed0d53
---> 0eae8eae7874
Removing intermediate container 75f353ed0d53
Step 10 : RUN cd /root
---> Running in feacbd998dd0
---> 284293ef46b0
Removing intermediate container feacbd998dd0
Step 11 : RUN bash -l -c "nvm install 0.10.31"
---> Running in 388514d11067
bash: nvm: command not found
2014/09/17 13:15:11 The command [/bin/sh -c bash -l -c "nvm install 0.10.31"] returned a non-zero         code: 127

Je suis assez nouveau dans Docker, donc il me manque peut-être quelque chose de fondamental dans l'écriture de Dockerfiles, mais jusqu'à présent, toutes les lectures que j'ai faites ne m'ont pas montré une bonne solution.

David Ficociello
la source
11
Pas un doublon car c'est particulier à l'installation à l'intérieur de docker et non à une installation standard
David Ficociello
Étant donné que vous n'installez qu'une seule version de node, il semble inutile d'installer nvm. Les Dockerfiles fournis par le référentiel de nœuds Docker peuvent être utilisés comme référence pour savoir comment installer le nœud.
mikwat

Réponses:

121

Lorsque vous exécutez à RUN bash...chaque fois un processus distinct, tout ce qui est défini dans l'environnement n'est pas conservé. Voici comment j'installe nvm:

# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

# Set debconf to run non-interactively
RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections

# Install base dependencies
RUN apt-get update && apt-get install -y -q --no-install-recommends \
        apt-transport-https \
        build-essential \
        ca-certificates \
        curl \
        git \
        libssl-dev \
        wget \
    && rm -rf /var/lib/apt/lists/*

ENV NVM_DIR /usr/local/nvm # or ~/.nvm , depending
ENV NODE_VERSION 0.10.33

# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.20.0/install.sh | bash \
    && . $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH      $NVM_DIR/v$NODE_VERSION/bin:$PATH
Abdullah Jibaly
la source
pour l'accélérer en deux fois, il suffit de passer v0.20.0àv0.24.1
itsnikolay
8
avec nvm 0.31.0et nœud, v4.2.3le chemin est/usr/local/nvm/versions/node/v4.2.3/bin
cwhsu
4
@thiagoh Cela n'explique pas pourquoi l'installation de NVM par l'interrogateur ne fonctionne pas et les réponses de travail fonctionnent. Cela n'a rien à voir avec les shells s'exécutant dans des processus séparés. C'est parce que la question tente de générer bash.rc pour charger le fichier nvm.sh qui charge la commande nvm dans bash, mais bash.rc se termine tôt lorsqu'il est exécuté de manière non interactive, donc la commande nvm n'est pas chargée. Toutes les réponses réussies source nvm.sh directement au lieu de le faire via bash.rc. C'est la clé pour faire ce travail.
tobuslieven
2
Au lieu de remplacer sh par bash, vous pouvez simplement le faire . $NVM_DIR/nvm.sh, en évitant le binaire source.
Razvan Grigore
3
Ceci est proche, mais les chemins nécessitent un petit ajustement, devraient être: ENV NODE_PATH $ NVM_DIR / versions / node / v $ NODE_VERSION / lib / node_modules ENV PATH $ NVM_DIR / versions / node / v $ NODE_VERSION / bin: $ PATH
Lunulata
31

Pour aider tous ceux qui recherchent un moyen d'installer Node.js avec NVM sur Ubuntu (dernière version), j'ai créé le fichier docker ci-dessous. J'utilise la dernière version de Docker, Ubuntu, Node.js et la NVM fonctionne correctement (le $ PATH a été corrigé). J'utilise ceci dans un environnement de production.

$ docker info \
Server Version: 1.9.1
Kernel Version: 4.1.13-boot2docker
Operating System: Boot2Docker 1.9.1 (TCL 6.4.1); master : cef800b - Fri Nov 20 19:33:59 UTC 2015

Node.js Version: stable 4.2.4 LTS
Ubuntu Version: 14.04.3


dockerfile:

FROM ubuntu:14.04.3

# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

# make sure apt is up to date
RUN apt-get update --fix-missing
RUN apt-get install -y curl
RUN apt-get install -y build-essential libssl-dev

ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 4.2.4

# Install nvm with node and npm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash \
    && source $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH      $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

RUN mkdir /usr/app
RUN mkdir /usr/app/log

WORKDIR /usr/app

# log dir
VOLUME /usr/app/log

# Bundle app source
COPY . /usr/app
# Install app dependencies
RUN npm install

EXPOSE  3000
CMD ["node", "server.js"]
danilodeveloper
la source
1
si le NODE_PATH ne doit pas être ENV NODE_PATH $ NVM_DIR / versions / node / v $ NODE_VERSION / lib / node_modules
Sentient
Bonjour @Sentient! J'exécute ce docker dans un environnement de production (ubuntu) et local dev (OSX), les deux fonctionnent correctement, sans erreurs. Utilisez-vous une NVM obsolète?
danilodeveloper
Y a-t-il une raison pour laquelle je devrais utiliser SUDO pour installer build-essential et libssl-dev? Je ne suis pas du tout un DevOps chevronné.
a.barbieri
1
La clé estsource $NVM_DIR/nvm.sh && nvm install $NODE_VERSION
Vladimir Kornea
24

Les chemins Nvm ont changé depuis la réponse acceptée, donc si vous souhaitez utiliser une version nvm plus à jour, vous devez apporter quelques modifications. En outre, il n'est pas nécessaire de remapper shpour le faire fonctionner:

ENV NVM_DIR /usr/local/nvm
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash
ENV NODE_VERSION v7.9.0
RUN /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION && nvm use --delete-prefix $NODE_VERSION"

ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/lib/node_modules
ENV PATH      $NVM_DIR/versions/node/$NODE_VERSION/bin:$PATH

Je ne sais pas si vous aurez besoin de l' --delete-prefixoption sur le nvm use- je l'ai fait, mais cela peut être quelque chose d'étrange dans mon image de base.

Steve Campbell
la source
1
Sauveur de vie! Si seulement j'avais vu votre réponse il y a 3 heures.
Adrian Marinica
A travaillé pour moi, image de base php: 7.1.1
Toby Mellor
18

Chacun RUNdans un Dockerfile est exécuté dans un conteneur différent. Donc, si vous sourcez un fichier dans un conteneur, son contenu ne sera pas disponible dans le suivant.

C'est pourquoi lorsque vous installez une application et que vous devez effectuer plusieurs étapes, vous devez le faire dans le même conteneur.

Avec votre exemple:

ADD files/nvm_install.sh /root/
RUN chmod a+x /root/nvm_install.sh && \
  /root/nvm_install.sh && \
  source /root/.bashrc && \
  cd /root && \
  nvm install 0.10.31
Kuhess
la source
OK, merci beaucoup pour l'explication. J'ai donc modifié mon script pour qu'il ressemble à ceci: `FROM ubuntu MAINTAINER dficociello ADD files / nvm_install.sh / root / # Install nvm RUN [" / bin / bash "," -c "," rm -f / etc / nginx / nginx.conf && touch /root/.bashrc && apt-get update && apt-get install nginx curl -y && chmod a + x /root/nvm_install.sh && source /root/.bashrc && / root / nvm_install. sh && nvm install 0.10.31 "] ADD files / nginx.conf / etc / nginx / EXPOSE 22` J'obtiens l'erreur suivante: `/ bin / bash: /root/nvm_install.sh: / bin / bash: interprète incorrect: Fichier texte occupé `
David Ficociello
Cette erreur doit être liée à votre ligne RUN ["/bin/bash", ...]. Il ne doit pas être entouré de [...]et vous n'avez pas besoin de spécifier l'interprète /bin/bash -c.
Kuhess le
17

Ceci est basé sur la meilleure réponse et fonctionne en 2018:

# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

# Install base dependencies
RUN apt-get update && apt-get install -y -q --no-install-recommends \
        apt-transport-https \
        build-essential \
        ca-certificates \
        curl \
        git \
        libssl-dev \
        wget

ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 8.11.3

WORKDIR $NVM_DIR

RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash \
    && . $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

ENV NODE_PATH $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules
ENV PATH      $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

Notez que ce nvmn'est pas une commande bash, c'est un alias. Cela peut vous gâcher si vous comptez sur $PATH.

rjurney
la source
15

Mise à jour du 20/02/2020 : Cette solution fonctionne si vous utilisez une debianimage de base. Si vous utilisez ubuntu, consultez cette réponse .

Voici le moyen le plus propre d'installer nvmque j'ai trouvé:

SHELL ["/bin/bash", "--login", "-c"]

RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
RUN nvm install 10.15.3

Explication

  • La première ligne définit le shell par défaut du Dockerfile sur un shell de connexion bash . Note: cela signifie que chaque suite RUN, CMDet ENTRYPOINTseront exécutés sous l'utilisateur actuel (généralement racine), et la source du ~ / .bashrc fichier si l' exécution en forme de coquille .

  • La deuxième ligne s'installe nvmavec bash. Lorsque le script est exécuté avec bash, il s'ajoute au fichier ~ / .bashrc .

  • La troisième ligne installe une version particulière de nodejs et l'utilise. Les nvm, npmet les nodecommandes sont disponibles car ils sont exécutés par un interpréteur de commandes bash (voir ligne 1).

Dominic Roy-Stang
la source
1
Merci beaucoup !
Gaui
Intéressant que cela fonctionne pour vous. J'ai essayé quelque chose de similaire et tout avait l'air bien pendant les builds, mais NPM n'a pas été trouvé lorsque je suis allé exécuter l'image résultante. Le réglage explicite NVM_DIR(comme indiqué dans plusieurs des autres réponses) l'a corrigé pour moi.
mail le
1
@esmail qui est étrange parce que les premiers RUNjeux de commandes NVM_DIRdans ~/.bashrc.
Dominic Roy-Stang le
1
@ DominicRoy-Stang, point valide. L'image avec laquelle je travaillais utilise shet donc ignore .bashrc. De plus, êtes-vous sûr que la .bashrcsource est vraiment fournie avant d'exécuter des RUNcommandes? Lors de mes brefs tests avec l' bashimage officielle , il me semblait que ce n'était pas le cas.
mail le
1
@esmail c'est ce à quoi la première ligne (l' SHELLinstruction) adresse. Il permet aux commandes RUN consécutives d'utiliser un shell de connexion qui source le .bashrcfichier. Remarque: cela ne fonctionne que si les commandes sont exécutées en mode shell, par exemple. RUN nvm --version. Cela ne fonctionnera pas si les commandes sont exécutées en mode exécution, par exemple. RUN ["nvm", "--version"]. J'ai mis à jour le lien que je fournis pour le formulaire shell afin de rendre cela plus évident.
Dominic Roy-Stang le
10

Sur la base de la suggestion de la réponse @Kuhess, j'ai remplacé la commande source par ce qui suit dans mon Dockerfile

RUN cat ~/.nvm/nvm.sh >> installnode.sh
RUN echo "nvm install 0.10.35" >> installnode.sh
RUN sh installnode.sh
Ryan
la source
8

Voici ma version de travail

FROM ubuntu:14.04

# Declare constants
ENV NVM_VERSION v0.29.0
ENV NODE_VERSION v5.0.0

# Replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

# Install pre-reqs
RUN apt-get update
RUN apt-get -y install curl build-essential

# Install NVM
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/${NVM_VERSION}/install.sh | bash

# Install NODE
RUN source ~/.nvm/nvm.sh; \
    nvm install $NODE_VERSION; \
    nvm use --delete-prefix $NODE_VERSION;

J'ai pris l'aide des réponses @abdulljibali et @shamisis.

Tahir Rauf
la source
Le sourcing du ~/.nvm/nvm.shfichier était la clé dont j'avais besoin.
Stephane
C'était la seule solution qui fonctionnait pour moi avec le conteneur ubuntu 16.04.2.
drohm
7

Je dois commencer par le fait que j'ai cherché partout pour obtenir un exemple fonctionnel de l' nvmintérieur dockeret que je n'en ai trouvé aucun. Même les réponses dans ce fil n'ont pas fonctionné.

Donc, j'ai passé un certain temps et en ai trouvé un qui fonctionne:

# install dependencies
RUN apt-get update && apt-get install -y \
      curl \
      npm \
      nodejs \
      git;

# compatibility fix for node on ubuntu
RUN ln -s /usr/bin/nodejs /usr/bin/node;

# install nvm
RUN curl https://raw.githubusercontent.com/creationix/nvm/v0.24.1/install.sh | sh;

# invoke nvm to install node
RUN cp -f ~/.nvm/nvm.sh ~/.nvm/nvm-tmp.sh; \
    echo "nvm install 0.12.2; nvm alias default 0.12.2" >> ~/.nvm/nvm-tmp.sh; \
    sh ~/.nvm/nvm-tmp.sh; \
    rm ~/.nvm/nvm-tmp.sh;

Remarquez comment j'ai également installé nodejsvia apt-get. J'ai trouvé que certains paquets ne sont pas installés dans docker à moins que cela ne soit fait.

Shamasis Bhattacharya
la source
yup - man - essayé environ 100 solutions et seule la vôtre fonctionne - 10x!
srfrnk
Correct pour utiliser ~ / .nvm / nvm-tmp.sh, donc les versions des nœuds sont installées correctement dans le répertoire ~ / .nvm
guidoman
7

Une différence clé entre la tentative d'obtenir la commande nvm dans la question:

RUN bash -l -c "source /root/.bashrc"

qui ne fonctionne pas et la tentative de faire de même dans la réponse acceptée:

source $NVM_DIR/nvm.sh

Est-ce que la deuxième version source directement le script nvm.sh, alors que l'original essaie de le faire via le fichier .bashrc.

Le fichier .bashrc contient une ligne au début qui se termine s'il est exécuté dans un shell non interactif:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
    *) return;;
esac

Ainsi, il n'atteint jamais le point où il aurait provoqué nvm.sh qui place réellement la commande nvm dans votre shell.

Je ne serais pas surpris si docker exécute ce truc dans un shell non interactif. Cela n'avait pas été explicitement souligné, alors j'ai pensé que je le mentionnerais car c'est ce qui m'a surpris quand je faisais quelque chose de similaire avec vagrant.

tobuslieven
la source
Merci d'avoir trouvé la source du problème. J'ai copié le fichier /etc/skel/.bashrc hors de l'image de base ubuntu 19.10, puis j'ai commenté les lignes incriminées ci-dessus. Ensuite, dans mon Dockerfile, j'ai utilisé la commande COPY pour copier un /etc/skel/.bashrc "corrigé" dans / etc / skel et seulement ensuite utiliser RUN pour créer des utilisateurs avec / bin / bash comme shell. Ensuite, les appels suivants à RUN ["/ bin / bash", "-c", "-l", YOUR_COMMAND [S] _HERE] ont bien fonctionné.
Stephan Doliov
6

Il m'a fallu une heure ou deux pour trouver le moyen le plus propre de le faire. --login ne semble pas exécuter .bashrc donc vous devez fournir -i pour le lancer en mode interactif. Cela amène Docker à vous crier dessus pendant un moment, je ne lance donc que de cette façon pour l'installation, puis je réinitialise mon shell standard.

# Installing Node
SHELL ["/bin/bash", "--login", "-i", "-c"]
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash
RUN source /root/.bashrc && nvm install 12.14.1
SHELL ["/bin/bash", "--login", "-c"]
user2896438
la source
Votre réponse m'a fait comprendre que la mienne ne fonctionne pas en ubuntutant qu'image de base (mais la vôtre le fait). J'utilisais des debianimages basées. Je ne sais pas ce qui cause l'écart entre les deux. Des idées?
Dominic Roy-Stang le
J'utilise ubuntu 19:10 comme image de base. Je publierai toutes les instructions Docker pertinentes afin que vous ayez une idée de ce qui fonctionne pour moi. Les instructions que j'ai omises ne sont pas pertinentes ou je ne peux pas les fournir. Je vais les représenter avec un commentaire. Je le
publierai
4

Rien de tout cela n'a fonctionné pour moi, pour mon python3-onbuildconteneur, j'ai dû créer de force des liens symboliques vers l'installation nvm.

# Install npm and nodejs
RUN apt-get install -y build-essential libssl-dev

RUN mkdir /root/.nvm
ENV NVM_DIR /root/.nvm
ENV NODE_VERSION 8.9.4

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.9/install.sh | bash
RUN chmod +x $HOME/.nvm/nvm.sh
RUN . $HOME/.nvm/nvm.sh && nvm install $NODE_VERSION && nvm alias default $NODE_VERSION && nvm use default && npm install -g npm

RUN ln -sf /root/.nvm/versions/node/v$NODE_VERSION/bin/node /usr/bin/nodejs
RUN ln -sf /root/.nvm/versions/node/v$NODE_VERSION/bin/node /usr/bin/node
RUN ln -sf /root/.nvm/versions/node/v$NODE_VERSION/bin/npm /usr/bin/npm
Corey Cole
la source
D'accord. Lors de l'installation dans un conteneur de docker (Debian GNU / Linux 9 (stretch)), nvm finit également $HOME/.nvmpour moi.
Dave Stevens
Oui, il fallait également ajouter des liens symboliques à moi. Je me demande comment les autres n'en ont même pas eu besoin.
PEZO
0

C'est ce qui a fonctionné pour moi (j'utilise debian buster):

RUN apt-get update
RUN apt-get install -y build-essential checkinstall libssl-dev
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.1/install.sh | bash
SHELL ["/bin/bash", "--login", "-c"]

Vous devriez maintenant pouvoir le faire nvm install <version>.

Alejandro Escobar
la source
0

Une seule réponse met l'installation curl mais ne fonctionne pas tout le Dockerfile

Voici mon Dockerfile prêt à copier / coller dans lequel j'installe la dernière version nvm 2020 avec Ubuntu 18.04.3 LTS

FROM ubuntu

RUN apt-get update
RUN echo "y" | apt-get install curl
ENV NVM_DIR /usr/local/nvm
RUN mkdir -p /usr/local/nvm
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
ENV NODE_VERSION v10
RUN /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION && nvm use --delete-prefix $NODE_VERSION"

ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/lib/node_modules
ENV PATH      $NVM_DIR/versions/node/$NODE_VERSION/bin:$PATH
JRichardsz
la source