134

我正在构建一个新的 Docker 映像,我正在寻找安装 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 还很陌生,所以我可能缺少一些编写 Dockerfile 的基础知识,但到目前为止,我所做的所有阅读都没有向我展示一个好的解决方案。

4

17 回答 17

146

当您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
于 2015-02-08T05:17:33.847 回答
46

更新 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 login shell。注意:这意味着每个后续RUNCMD, 和ENTRYPOINT都将在当前用户(通常是 root)下运行,如果以shell 形式运行,则源~/.bashrc文件。

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

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

于 2019-08-04T05:59:05.087 回答
38

为了帮助所有正在寻找在 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


码头文件:

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"]
于 2016-01-04T13:09:09.980 回答
30

自接受答案以来,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,但这可能对我的基本图像有些奇怪。

于 2017-04-19T13:52:06.447 回答
23

我花了一两个小时才找到最干净的方法。--login 似乎没有执行 .bashrc 所以你必须提供 -i 以在交互模式下启动它。这会导致 Docker 对你大喊一声,所以我只以这种方式启动安装,然后重置为我的标准 shell。

# 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"]
于 2020-02-09T14:59:13.453 回答
21

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
于 2014-09-17T20:56:25.327 回答
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.

于 2018-06-20T23:11:36.593 回答
11

这是我的工作版本

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 的答案中得到帮助。

于 2015-11-27T19:12:19.777 回答
10

根据@Kuhess 回答中的建议,我在 Dockerfile 中将 source 命令替换为以下内容

RUN cat ~/.nvm/nvm.sh >> installnode.sh
RUN echo "nvm install 0.10.35" >> installnode.sh
RUN sh installnode.sh
于 2015-02-08T01:25:05.700 回答
9

只有一个答案是 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
于 2020-07-10T16:42:10.493 回答
8

尝试在问题中获取 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 中运行这些东西,我不会感到惊讶。这没有被明确指出,所以我想我会提到它,因为当我对 vagrant 做类似的事情时,这让我感到很震惊。

于 2016-07-24T17:34:42.613 回答
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;

请注意我是如何安装nodejsapt-get。我发现除非这样做,否则某些软件包不会安装在 docker 中。

于 2015-04-15T20:52:03.120 回答
5

这些都不适合我,对于我的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
于 2018-04-24T01:12:55.367 回答
5

2021 年 2 月 25 日主要问题是使用 'source' 指令,这是 bash shell 特有的。对我有用的是用“。”替换“来源”。对于 Ubuntu 18 安装。我的 Dockerfile:

FROM ubuntu:bionic

RUN \
  apt update && \
  apt upgrade -y && \
  apt install -y curl

ENV NVM_DIR /root/.nvm
ENV NODE_VERSION 14.16

# Install nvm with node and npm
RUN curl -sL https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash \
  && . $NVM_DIR/nvm.sh \ 
  && nvm install $NODE_VERSION
于 2021-02-25T14:50:12.693 回答
2

这对我有用(我正在使用 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>

于 2020-05-24T17:37:18.637 回答
2

这会在扩展图像“php:7.4.15”(debian:buster-slim) 时安装 nodejs 的 lts 版本:

# Install nvm to install npm and node.js
ENV NVM_DIR /root/.nvm
ENV NODE_VERSION lts/*
RUN mkdir $HOME/.nvm && \
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash && \
    chmod +x $HOME/.nvm/nvm.sh && \
    . $HOME/.nvm/nvm.sh && \
    nvm install --latest-npm "$NODE_VERSION" && \
    nvm alias default "$NODE_VERSION" && \
    nvm use default && \
    DEFAULT_NODE_VERSION=$(nvm version default) && \
    ln -sf /root/.nvm/versions/node/$DEFAULT_NODE_VERSION/bin/node /usr/bin/nodejs && \
    ln -sf /root/.nvm/versions/node/$DEFAULT_NODE_VERSION/bin/node /usr/bin/node && \
    ln -sf /root/.nvm/versions/node/$DEFAULT_NODE_VERSION/bin/npm /usr/bin/npm
于 2021-03-07T20:51:05.977 回答
0

nvm not found可能是因为它是为与执行容器的用户不同的用户安装的。您可能需要使用正在执行容器的自定义用户作为安装前缀。最后一条USER语句定义了容器用户。

USER $USERNAME

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

原因

潜入nvm安装脚本,例如v0.39.1,可以看到它已安装到$HOME当前用户。如果您没有更改它,则ubuntu图像的默认用户是root. 但是,当使用其他用户启动容器时,nvm将找不到;因此确保安装和执行的用户对齐。

nvm_default_install_dir() {
  [ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm"
}
于 2022-02-11T12:27:34.067 回答