如何在Docker中安装NVM?


101

我正在构建一个新的Docker映像,并且希望安装NVM,以便可以管理nodejs。

阅读有关如何安装NVM的文档时,他们提到要开始使用NVM,您需要获取.bashrc文件的源。

我尝试在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的新手,所以我可能缺少编写Dockerfile的基本知识,但是到目前为止,我所做的所有阅读都没有向我展示好的解决方案。


11
不是重复的,因为这是特定于docker内部安装的,而不是标准安装
docker David Ficociello 2014年

由于您仅安装单个版本的节点,因此似乎无需安装nvm。Docker提供的Dockerfile节点存储库可以用作如何安装节点的参考。
mikwat

Answers:


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.0v0.24.1
itsnikolay 2015年

8
与nvm 0.31.0和节点v4.2.3的路径是/usr/local/nvm/versions/node/v4.2.3/bin
cwhsu 16/04/29

4
@thiagoh这不能解释为什么发问者安装nvm不能正常工作,而有效答案却可以正常工作。它与在单独的进程中运行的外壳无关。这是因为该问题尝试将bash.rc的源文件加载到将nvm命令加载到bash中的nvm.sh文件中,但是bash.rc在以非交互方式运行时会较早退出,因此不会加载nvm命令。所有成功的答案都直接来自nvm.sh,而不是通过bash.rc执行。这是完成这项工作的关键。
tobuslieven

2
不用用bash代替sh,您可以简单地这样做. $NVM_DIR/nvm.sh,避免源二进制文件。
拉兹万格里戈尔

3
这很接近,但是路径需要稍作调整,应为: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

为了帮助正在寻找在Ubuntu(最新版本)上使用NVM安装Node.js的所有人,我在下面制作了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 / versions / node / v $ NODE_VERSION / lib / node_modules
Sentient

您好@Sentient!我正在生产环境(ubuntu)和本地开发人员(OSX)中运行此docker,它们都可以正常工作,没有错误。您是否正在运行过时的NVM?
danilodeveloper

为什么我应该使用SUDO安装build-essential和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
救生员!如果我三个小时前才看到您的回复。
阿德里安·马里尼卡

为我工作,基本图像php:7.1.1
Toby Mellor

18

RUNDockerfile中的每个文件都在不同的容器中执行。因此,如果您在容器中获取文件,则其内容将在下一个文件中不可用。

这就是为什么当您安装应用程序并且需要执行几个步骤时,必须在同一容器中执行该操作的原因。

以您的示例为例:

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

好的,非常感谢您的解释。因此,我已经修改了脚本,如下所示:`FROM ubuntu MAINTAINER dficociello ADD files / nvm_install.sh / root /#安装nvm RUN [“ / bin / bash”,“ -c”,“ rm -f / etc / nginx / nginx.conf &&触摸/root/.bashrc && apt-get更新&& apt-get安装nginx curl -y && chmod a + x /root/nvm_install.sh &&源/root/.bashrc && / root / nvm_install。 sh && nvm install 0.10.31“]添加文件/nginx.conf / etc / nginx / EXPOSE 22`我得到以下错误:`/ bin / bash:/root/nvm_install.sh:/ bin / bash:错误的解释器:文本文件忙碌`
David Ficociello 2014年

此错误必须链接到您的线路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的默认shell设置为bash登录shell。注:这意味着每个随后RUNCMDENTRYPOINT将在当前用户(通常是root)下运行,并且如果以shell形式运行,则将〜/ .bashrc文件作为源。

  • 第二行安装 nvm使用bash。当脚本使用bash运行时,它将追加到〜/ .bashrc文件中。

  • 第三行安装并使用特定版本的nodejs。的nvmnpm以及node因为它们通过bash登录shell(参照第1行)运行的命令是可用的。


1
非常感谢 !
加伊

有趣的是,这为您工作。我尝试了类似的操作,并且在构建过程中一切看起来都很好,但是当我运行生成的图像时却找不到NPM。显式设置NVM_DIR(如其他几个答案所示)为我修复了该问题。
电子邮件

1
@esmail很奇怪,因为第一个RUN命令设置NVM_DIR在中~/.bashrc
Dominic Roy-Stang

1
@ DominicRoy-Stang,有效点。我使用的图像使用了sh,因此忽略了.bashrc。另外,.bashrc在执行RUN命令之前,您确定确实是来源吗?在我对官方bash形象的简短测试中,似乎并非如此。
电子邮件

1
@esmail是第一行(SHELL指令)所处理的内容。它使连续的RUN命令使用登录外壳程序来获取.bashrc文件。注意:仅当命令在外壳模式下运行时,它才有效。RUN nvm --version。如果命令在exec模式下运行,则它将不起作用。RUN ["nvm", "--version"]。我已经更新了我为shell表单提供的链接,希望可以使这一点变得更加明显。
Dominic Roy-Stang

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文件是我需要的关键。
Stephane

这是唯一适用于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为好。我发现除非完成此操作,否则某些软件包不会安装在docker内部。


是的-男人-尝试了大约100种解决方案,只有您自己的解决方案-10倍!
srfrnk

正确使用〜/ .nvm / nvm-tmp.sh,因此节点版本已正确安装在〜/ .nvm目录中
guidoman

6

尝试获取问题中的nvm命令之间的主要区别:

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

这不起作用,并且在接受的答案中尝试执行相同的操作:

source $NVM_DIR/nvm.sh

是第二个版本直接获取nvm.sh脚本,而原始版本则尝试通过.bashrc文件执行此操作。

.bashrc文件的开头有一行,如果它在非交互式shell中运行,则该行会退出:

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

因此,它永远都无法达到将nvm.sh来源的目的,后者实际上将nvm命令放入您的shell中。

如果docker在非交互式shell中运行这些东西,我不会感到惊讶。没有明确指出这一点,所以我想提一下它,因为当我对流浪汉做类似的事情时,这才吸引了我。


感谢您找到问题的根源。我从基本的ubuntu 19.10映像中复制了/etc/skel/.bashrc文件,然后注释了上述令人讨厌的行。然后在我的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基于图像的图像。我不确定是什么导致两者之间的差异。有任何想法吗?
Dominic Roy-Stang

我正在使用ubuntu 19:10作为基本图像。我将发布所有相关的Docker指令,以便您对自己的工作有所了解。我遗漏的任何说明都不相关或无法提供。我将用评论代表他们。由于字符数限制设置太低,我将在下
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

同意 在docker容器中安装(Debian GNU / Linux 9(stretch))时,nvm也$HOME/.nvm对我有用。
Dave Stevens

是的,符号链接也是必须添加到我的。我想知道其他人甚至不需要它。
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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.