Jak zainstalować nvm w dockerze?


101

Jestem w trakcie tworzenia nowego obrazu Dockera i szukam zainstalowania NVM, abym mógł zarządzać nodejs.

Czytając dokumentację o tym, jak zainstalować NVM, wspominają, że musisz pobrać plik .bashrc, aby rozpocząć korzystanie z NVM.

Próbowałem to ustawić w pliku Dockerfile, ale jak dotąd kompilacja kończy się niepowodzeniem z powodu błędu:

„bash: nvm: nie znaleziono polecenia”

Oto odpowiednie wiersze z mojego pliku 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"

Oto wynik próby zbudowania:

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

Jestem całkiem nowy w Dockerze, więc być może brakuje mi czegoś podstawowego do pisania Dockerfiles, ale jak dotąd cała lektura, którą zrobiłem, nie pokazała mi dobrego rozwiązania.


11
Nie jest to duplikat, ponieważ dotyczy to instalacji wewnątrz dockera i nie jest standardową instalacją
David Ficociello

Ponieważ instalujesz tylko jedną wersję węzła, instalowanie nvm wydaje się niepotrzebne. Pliki Dockerfiles dostarczone przez repozytorium węzłów platformy Docker mogą służyć jako odniesienie do sposobu instalowania węzła.
mikwat

Odpowiedzi:


121

Za RUN bash...każdym razem, gdy jest uruchamiany w oddzielnym procesie, nic ustawione w środowisku nie jest obsługiwane. Oto jak instaluję 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

aby przyspieszyć to dwukrotnie, po prostu zmień v0.20.0nav0.24.1
itsnikolay

8
z nvm 0.31.0i węzłem v4.2.3ścieżka to/usr/local/nvm/versions/node/v4.2.3/bin
cwhsu

4
@thiagoh To nie wyjaśnia, dlaczego instalacja nvm przez pytającego nie działa, a działające odpowiedzi działają. Nie ma to nic wspólnego z powłokami działającymi w oddzielnych procesach. Dzieje się tak, ponieważ pytanie próbuje pobrać źródło bash.rc, aby załadować plik nvm.sh, który ładuje polecenie nvm do bash, ale bash.rc kończy działanie wcześniej, gdy jest uruchamiany w trybie nieinteraktywnym, więc polecenie nvm nie jest ładowane. Wszystkie pomyślne odpowiedzi pochodzą bezpośrednio z nvm.sh zamiast robić to przez bash.rc. To jest klucz do wykonania tej pracy.
tobuslieven

2
Zamiast zamieniać sh na bash, możesz po prostu to zrobić . $NVM_DIR/nvm.sh, unikając źródłowego pliku binarnego.
Razvan Grigore

3
To jest blisko, ale ścieżki wymagają niewielkiej korekty, powinny wyglądać następująco: 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

Aby pomóc wszystkim, którzy szukają sposobu na zainstalowanie Node.js z NVM na Ubuntu (ostatnia wersja), utworzyłem poniżej plik dockerfile. Używam ostatniej wersji Dockera, Ubuntu, Node.js i NVM działa poprawnie (poprawiono $ PATH). Używam tego w środowisku produkcyjnym.

$ 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"]

1
czy NODE_PATH nie powinno być ENV NODE_PATH $ NVM_DIR / Versions / node / v $ NODE_VERSION / lib / node_modules
Sentient

Witaj @Sentient! Używam tego dockera w środowisku produkcyjnym (ubuntu) i lokalnym (OSX), oba działają poprawnie, bez błędów. Czy używasz przestarzałego NVM?
danilodeveloper

Czy jest powód, dla którego powinienem używać SUDO do instalacji build-essential i libssl-dev? Wcale nie jestem doświadczonym DevOps.
a.barbieri

1
Kluczem jestsource $NVM_DIR/nvm.sh && nvm install $NODE_VERSION
Vladimir Kornea

24

Ścieżki NVM zmieniły się od czasu zaakceptowania odpowiedzi, więc jeśli chcesz użyć bardziej aktualnej wersji NVM, musisz wprowadzić kilka zmian. Nie jest też konieczne ponowne mapowanie, shaby działało:

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

Nie jestem pewien, czy będziesz potrzebować --delete-prefixopcji nvm use- tak, ale to może być coś dziwnego w moim podstawowym obrazie.


1
Oszczędza życie! Gdybym tylko widział Twoją odpowiedź 3 godziny temu.
Adrian Marinica,

Pracował dla mnie, obraz podstawowy php: 7.1.1
Toby Mellor

18

Każdy RUN plik Dockerfile jest wykonywany w innym kontenerze. Więc jeśli pobierzesz plik w kontenerze, jego zawartość nie będzie dostępna w następnym.

Dlatego gdy instalujesz aplikację i musisz wykonać kilka kroków, musisz to zrobić w tym samym kontenerze.

Z twoim przykładem:

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

OK, bardzo dziękuję za wyjaśnienie. Więc zmodyfikowałem mój skrypt tak, aby wyglądał następująco: `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 "] DODAJ pliki / nginx.conf / etc / nginx / EXPOSE 22` Otrzymuję następujący błąd: `/ bin / bash: /root/nvm_install.sh: / bin / bash: zły interpreter: Plik tekstowy zajęty `
David Ficociello

Ten błąd musi być powiązany z Twoją linią RUN ["/bin/bash", ...]. Nie może być otoczone [...]ani nie musisz określać tłumacza /bin/bash -c.
Kuhess

17

Jest to oparte na najlepszej odpowiedzi i działa w 2018 roku:

# 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

Zauważ, że nvmnie jest to polecenie bash, to alias. To może cię zepsuć, jeśli polegasz $PATH.


15

Aktualizacja 20.02.2020 : To rozwiązanie działa, jeśli używasz debianobrazu podstawowego. Jeśli używasz ubuntu, zobacz tę odpowiedź .

Oto najczystszy sposób instalacji nvm, jaki znalazłem:

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

Wyjaśnienie

  • Pierwsza linia ustawia domyślną powłokę pliku Dockerfile na powłokę logowania bash . Uwaga: To oznacza, że każdy kolejny RUN, CMDi ENTRYPOINTbędą prowadzone w ramach bieżącego użytkownika (zazwyczaj root), a źródłowy ~ / .bashrc plik jeśli prowadzony w formie muszli .

  • Druga linia instaluje się nvmz bash. Gdy skrypt jest uruchamiany za pomocą basha, dołącza go do pliku ~ / .bashrc .

  • Trzecia linia instaluje określoną wersję nodejs i używa jej. Polecenia nvm, npmi nodesą dostępne, ponieważ są uruchamiane przez powłokę logowania bash (zobacz wiersz 1).


1
Dziękuję bardzo !
Gaui

Ciekawe, że to działało dla ciebie. Próbowałem czegoś podobnego i wszystko wyglądało dobrze podczas kompilacji, ale nie znaleziono NPM, gdy poszedłem uruchomić wynikowy obraz. Jawne ustawienie NVM_DIR(jak pokazano w kilku innych odpowiedziach) naprawiło to za mnie.
e

1
@esmail to dziwne, ponieważ ustawiono pierwsze RUNpolecenieNVM_DIR w ~/.bashrc.
Dominic Roy-Stang

1
@ DominicRoy-Stang, ważny punkt. Obraz, z którym pracowałem, używa shi dlatego jest ignorowany .bashrc. Czy na pewno .bashrcjest on rzeczywiście pozyskiwany przed wykonaniem RUNpoleceń? Podczas moich krótkich testów z urzędnikiembash obrazem wydawało się, że tak nie jest.
e

1
@esmail to jest adres w pierwszej linii ( SHELLinstrukcja). Powoduje, że kolejne polecenia RUN używają powłoki logowania, która pozyskuje .bashrcplik. Uwaga: działa tylko wtedy, gdy polecenia są uruchamiane w trybie powłoki, np. RUN nvm --version. Nie będzie działać, jeśli polecenia są uruchamiane w trybie exec, np. RUN ["nvm", "--version"]. Zaktualizowałem łącze, które udostępniam dla formularza powłoki, aby, mam nadzieję, uczynić to bardziej oczywistym.
Dominic Roy-Stang

10

Opierając się na sugestii w odpowiedzi @Kuhess, zastąpiłem polecenie źródła następującym w moim pliku Dockerfile

RUN cat ~/.nvm/nvm.sh >> installnode.sh
RUN echo "nvm install 0.10.35" >> installnode.sh
RUN sh installnode.sh

8

Oto moja wersja robocza

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;

Skorzystałem z pomocy odpowiedzi @abdulljibali i @shamisis.


Pozyskiwanie ~/.nvm/nvm.shpliku było kluczem, którego potrzebowałem.
Stephane

To było jedyne rozwiązanie, które działało dla mnie z kontenerem Ubuntu 16.04.2.
drohm

7

Muszę zacząć od tego, że szukałem wszędzie, aby uzyskać działający przykład nvmwnętrzadocker ale nie znalazłem. Nawet odpowiedzi w tym wątku nie zadziałały.

Spędziłem więc trochę czasu i wymyśliłem taki, który działa:

# 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;

Wskazówki jak mam zainstalowane nodejspoprzez apt-getjak również. Zauważyłem, że niektóre pakiety nie są instalowane wewnątrz dockera, chyba że zostanie to zrobione.


yup - stary - wypróbowałem około 100 rozwiązań i tylko twoje działa - 10x!
srfrnk

Poprawne użycie ~ / .nvm / nvm-tmp.sh, więc wersje węzłów są poprawnie instalowane w katalogu ~ / .nvm
guidoman

7

Kluczowa różnica między próbą uzyskania polecenia nvm w pytaniu:

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

co nie działa i próba zrobienia tego samego w zaakceptowanej odpowiedzi:

source $NVM_DIR/nvm.sh

Czy to druga wersja bezpośrednio źródła skryptu nvm.sh, podczas gdy oryginał próbuje to zrobić za pośrednictwem pliku .bashrc.

Plik .bashrc zawiera wczesną linię, która kończy pracę, jeśli jest uruchamiany w powłoce nieinteraktywnej:

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

Tak więc nigdy nie dochodzi do miejsca, w którym mógłby uzyskać plik nvm.sh, który faktycznie umieszcza polecenie nvm w powłoce.

Nie zdziwiłbym się, gdyby docker uruchamiał te rzeczy w powłoce nieinteraktywnej. Nie zostało to wyraźnie zaznaczone, więc pomyślałem, że wspomnę o tym, ponieważ to mnie zaskoczyło, gdy robiłem coś podobnego z włóczęgą.


Dziękuję za znalezienie źródła problemu. Skopiowałem plik /etc/skel/.bashrc z podstawowego obrazu ubuntu 19.10, a następnie zakomentowałem powyższe obraźliwe wiersze. Następnie w moim pliku Dockerfile użyłem polecenia COPY, aby skopiować „poprawiony” /etc/skel/.bashrc do / etc / skel i dopiero potem użyć RUN do tworzenia użytkowników z / bin / bash jako powłoką. Następnie kolejne wywołania RUN ["/ bin / bash", "-c", "-l", YOUR_COMMAND [S] _HERE] działały poprawnie.
Stephan Doliov

6

Zajęło mi godzinę lub dwie, zanim wymyśliłem najczystszy sposób, aby to zrobić. --login nie wydaje się wykonywać .bashrc, więc musisz podać -i, aby uruchomić go w trybie interaktywnym. To powoduje, że Docker krzyczy na ciebie przez chwilę, więc uruchamiam w ten sposób tylko w celu instalacji, a następnie resetuję do mojej standardowej powłoki.

# 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"]

Twoja odpowiedź uświadomiła mi, że mój nie działa ubuntujako obraz bazowy (ale twój działa). Używałem debianobrazów oparte. Nie jestem pewien, co powoduje rozbieżność między nimi. Jakieś pomysły?
Dominic Roy-Stang

Używam ubuntu 19:10 jako obrazu podstawowego. Opublikuję wszystkie istotne instrukcje dotyczące Dockera, abyś wiedział, co działa u mnie. Wszelkie instrukcje, które pominąłem, są nieistotne lub nie mogę ich udzielić. Przedstawię ich komentarzem. Opublikuję to w następnym komentarzu, ponieważ limit znaków jest ustawiony zbyt niski
Opublikuję

4

Żadne z nich nie działało dla mnie, ponieważ w moim python3-onbuildkontenerze musiałem wymusić tworzenie dowiązań symbolicznych do instalacji 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

Zgoda. Podczas instalacji w kontenerze docker (Debian GNU / Linux 9 (stretch)), nvm również trafia $HOME/.nvmdo mnie.
Dave Stevens

Tak, linki symboliczne też były potrzebne, aby mnie dodać. Zastanawiam się, jak inni nawet tego nie potrzebowali.
PEZO

0

Oto, co zadziałało dla mnie (używam 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"]

Teraz powinieneś być w stanie to zrobić nvm install <version>.


0

Tylko jedna odpowiedź umieściła instalację curl, ale nie działa w całym pliku Dockerfile

Tutaj mój plik Dockerfile gotowy do kopiowania / wklejania, w którym instaluję najnowszą wersję nvm 2020 z 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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.