Як встановити nvm в docker?


101

Я будую новий образ Докера і хочу встановити NVM, щоб я міг керувати nodejs.

Читаючи документи про те, як встановити NVM, вони згадують, що вам потрібно джерело файлу .bashrc, щоб почати використовувати NVM.

Я намагався налаштувати це в Dockerfile, але поки що будівництво не вдається з помилкою:

"bash: nvm: команда не знайдена"

Ось відповідні рядки з мого 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"

Ось результат спроби побудови:

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

Я досить новачок у Docker, тому, можливо, мені не вистачає чогось принципового для написання Dockerfiles, але поки що все прочитане я не показав мені гарного рішення.


11
Не дублікат, оскільки це особливо для встановлення всередині докера, а не для стандартної установки
David Ficociello

Оскільки ви встановлюєте лише одну версію вузла, видавати nvm видається непотрібним. Докерфіли, надані сховищем вузла Докер, можуть використовуватися як орієнтир щодо встановлення вузла.
mikwat

Відповіді:


121

Коли ви RUN bash...кожен раз працюєте в окремому процесі, все, що встановлюється в оточенні, не підтримується. Ось як я встановив 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

щоб пришвидшити його в два рази, просто змініть v0.20.0наv0.24.1
itsnikolay

8
з nvm 0.31.0та node v4.2.3шлях/usr/local/nvm/versions/node/v4.2.3/bin
cwhsu

4
@thiagoh Це не пояснює, чому встановлення nvm запитувача не працює і чи працюють відповіді. Це не має нічого спільного з оболонками, що працюють в окремих процесах. Це тому, що питання намагається створити bash.rc для завантаження файлу nvm.sh, який завантажує команду nvm в bash, але bash.rc запускається рано при запуску неінтерактивно, тому команда nvm не завантажується. Усі успішні джерела відповідей nvm.sh безпосередньо, а не робити це через bash.rc. Це ключ до створення цієї роботи.
tobuslieven

2
Замість заміни sh на bash, ви можете просто зробити . $NVM_DIR/nvm.sh, уникаючи бінарних джерел.
Разван Григоре

3
Це близько, але шляхи потребують невеликого коригування, повинні бути: ENV NODE_PATH $ NVM_DIR / версії / node / v $ NODE_VERSION / lib / node_modules ENV PATH $ NVM_DIR / версії / вузол / v $ NODE_VERSION / bin: $ PATH
Lunulata

31

Щоб допомогти всім, хто шукає спосіб встановити Node.js з NVM на Ubuntu (остання версія), я зробив dockerfile нижче. Я використовую останню версію Docker, Ubuntu, Node.js і NVM працює належним чином ($ PATH було виправлено). Я використовую це у виробничих умовах.

$ 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
якщо NODE_PATH не буде ENV NODE_PATH $ NVM_DIR / версії / вузол / v $ NODE_VERSION / lib / node_modules
Sentient

Привіт @Sentient! Я запускаю цей докер у виробничому середовищі (ubuntu) та локальному розробнику (OSX), обидва працюють належним чином, без помилок. Можливо, у вас працює застарілий NVM?
danilodeveloper

Чи є причина, чому я повинен використовувати SUDO для встановлення build-basic та libssl-dev? Я зовсім не досвідчений DevOps.
a.barbieri

1
Ключsource $NVM_DIR/nvm.sh && nvm install $NODE_VERSION
Володимир

24

Шлях Nvm змінився з моменту прийнятої відповіді, тому, якщо ви хочете використовувати більш сучасну версію nvm, вам потрібно внести кілька змін. Крім того, не потрібно робити перезавантаження, shщоб змусити його працювати:

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

Не впевнений, чи потрібна вам --delete-prefixопція на nvm use- я це зробив, але це може бути щось дивне в моєму базовому зображенні.


1
Рятувальник життя! Якби я бачив твою відповідь 3 години тому.
Адріан Марініка

Працював для мене, базове зображення php: 7.1.1
Тобі Меллор

18

Кожен RUNв Dockerfile виконується в іншому контейнері. Отже, якщо ви джерело файлу в контейнері, його вміст буде недоступним у наступному.

Ось чому, коли ви встановлюєте додаток і вам потрібно зробити кілька кроків, ви повинні зробити це в одному контейнері.

З вашим прикладом:

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

Добре, дуже дякую за пояснення. Тому я змінив свій сценарій, щоб виглядати так: `З ubuntu MAINTAINER dficociello ADD файли / nvm_install.sh / root / # Установити nvm RUN [" / bin / bash "," -c "," rm -f / тощо / 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 файли / nginx.conf / etc / nginx / EXPOSE 22` Я отримую таку помилку: `/ bin / bash: /root/nvm_install.sh: / bin / bash: поганий інтерпретатор: Текстовий файл зайнятий `
David Ficociello

Ця помилка повинна бути пов’язана з вашою лінією RUN ["/bin/bash", ...]. Він не повинен бути оточений, [...]і вам не потрібно вказувати перекладача /bin/bash -c.
Kuhess

17

Це ґрунтується на головній відповіді та працює у 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

Зауважте, що nvmце не команда bash, це псевдонім. Це може згубити вас, якщо ви покладаєтесь $PATH.


15

Оновлення 20.02.2020 : Це рішення працює, якщо ви використовуєте debianбазове зображення. Якщо ви використовуєте ubuntu, дивіться цю відповідь .

Ось найпростіший спосіб встановлення, nvmякий я знайшов:

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

Пояснення

  • Перший рядок встановлює оболонку Dockerfile за замовчуванням на оболонку входу . Примітка: це означає, що кожен наступний RUN, CMDі ENTRYPOINTбуде запускатися під поточним користувачем (як правило, root), і джерело файлу ~ / .bashrc, якщо він запускається у формі оболонки .

  • Другий рядок встановлюється nvmз bash. Коли сценарій запускається з bash, він додається до файла ~ / .bashrc .

  • Третій рядок встановлює певну версію nodejs та використовує її. В nvm, npmі nodeкоманди доступні , тому що вони працюють через Баш оболонку входу (див рядок 1).


1
Дуже дякую !
Гауї

Цікаво, що це працювало для вас. Я спробував щось подібне, і все виглядало нормально під час складання, але NPM не було знайдено, коли я пішов запускати отримане зображення. Явна установка NVM_DIR(як показано в кількох інших відповідях) зафіксувала це для мене.
esmail

1
@esmail це дивно, тому що перша RUNкоманда встановлюється NVM_DIRв ~/.bashrc.
Домінік Рой-Штанг

1
@ DominicRoy-Stang, дійсна точка. Образ, з яким я працював, використовує shі тому ігнорує .bashrc. Також ви впевнені, що .bashrcце дійсно знайдено перед виконанням RUNкоманд? У моєму короткому тестуванні з офіційним bashзображенням здавалося, що це не так.
esmail

1
@esmail саме так адресується перший рядок ( SHELLінструкція). Це робить послідовні команди RUN використовувати оболонку входу, яка джерела .bashrcфайлу. Примітка: вона працює лише в тому випадку, якщо команди виконуються в режимі оболонки, наприклад. RUN nvm --version. Він не працюватиме, якщо команди виконуються у режимі exec, наприклад. RUN ["nvm", "--version"]. Я оновив посилання, яке я надаю для форми оболонки, щоб сподіватися зробити це більш очевидним.
Домінік Рой-Штанг

10

На основі пропозиції у відповіді @Kuhess я замінив початкову команду на наступну у своєму Dockerfile

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

8

Ось моя робоча версія

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;

Допоможи у відповідях @abdulljibali та @shamisis.


Шукати ~/.nvm/nvm.shфайл був потрібним мені ключем.
Стефан

Це єдине рішення, яке працювало для мене з контейнером ubuntu 16.04.2.
drohm

7

Я повинен почати з того, що я шукав всюди, щоб отримати робочий приклад nvmвсередині, dockerі я не знайшов жодного. Навіть відповіді в цій темі не спрацювали.

Отже, я витратив досить багато часу і придумав таке, що працює:

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

Зверніть увагу , як я встановив nodejsчерез apt-getа. Я виявив, що деякі пакети не встановлюються всередині докера, якщо це не зроблено.


yup-man - спробував близько 100 рішень і тільки твої роботи - 10х!
srfrnk

Правильно використовувати ~ / .nvm / nvm-tmp.sh, тому версії вузлів правильно встановлені всередині каталогу ~ / .nvm
guideoman

6

Ключова різниця між спробою отримати команду nvm у питанні:

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

що не працює і спроба зробити те саме у прийнятій відповіді:

source $NVM_DIR/nvm.sh

Хіба що друга версія безпосередньо джерело сценарію nvm.sh, тоді як оригінал намагається зробити це через файл .bashrc.

У файлі .bashrc на початку є рядок, який виходить, якщо він запускається в неінтерактивній оболонці:

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

Таким чином, він ніколи не потрапляє на біт, де він створив би nvm.sh, який насправді додає команду nvm у вашу оболонку.

Я не був би здивований, якщо докер виконує цей матеріал у неінтерактивній оболонці. Це не було чітко зазначено, тому я думав, що згадаю це, бо саме це мене зловило, коли я робив щось подібне з бродяжником.


Дякуємо, що знайшли джерело проблеми. Я скопіював файл /etc/skel/.bashrc з базового зображення ubuntu 19.10, а потім прокоментував вищезазначені рядки. Потім у своєму Dockerfile я використав команду COPY, щоб скопіювати "виправлений" /etc/skel/.bashrc в / etc / skel, і лише після цього використовувати RUN для створення користувачів з / bin / bash як їх оболонки. Потім наступні дзвінки на RUN ["/ bin / bash", "-c", "-l", YOUR_COMMAND [S] _HERE] спрацювали чудово.
Стефан Дольов

6

Мені потрібна година-дві, щоб зрозуміти найчистіший спосіб зробити це. --login не здається виконувати .bashrc, тому вам доведеться поставити -i, щоб запустити його в інтерактивному режимі. Це змушує Docker трохи кричати на вас, тому я лише запускаю цей шлях для встановлення, а потім скидаю на стандартну оболонку.

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

Ваша відповідь дала мені зрозуміти, що моя не працює, використовуючи ubuntuяк базовий образ (але це так). Я використовував debianосновані зображення. Я не впевнений, що викликає розбіжність між ними. Якісь ідеї?
Домінік Рой-Штанг

Я використовую ubuntu 19:10 в якості базового зображення. Я опублікую всі відповідні інструкції Докера, щоб ви мали уявлення про те, що для мене працює. Будь-які інструкції, які я випустив, або не стосуються, або я не можу надати. Я представляю їх із коментарем. Я опублікую його в наступному коментарі, оскільки обмеження кількості персонажів встановлено занадто низько
user2896438

4

Нічого з них не працювало для мене, для свого python3-onbuildконтейнера мені довелося змусити створити символічні посилання на 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

Домовились. Під час установки в контейнер докера (Debian GNU / Linux 9 (stretch)), nvm також закінчується $HOME/.nvmдля мене.
Дейв Стівенс

Так, символічні посилання були необхідні і для мене. Мені цікаво, як інші навіть не потребували цього.
PEZO

0

Це для мене працювало (я використовую 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"]

Тепер ви повинні вміти робити nvm install <version>.


0

Лише одна відповідь ставить встановлення curl, але не працює на весь Dockerfile

Ось мій Dockerfile готовий до копіювання / вставки, в який я встановлюю останню версію nvm 2020 з 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.