如何在 docker 中安装 nvm?

我正在构建一个新的 Docker 映像的过程中,我希望得到 NVM 安装,以便我可以管理 nodejs。

阅读关于如何安装 NVM 的文档,他们提到您需要为您的。文件,以便开始使用 NVM。

我已经尝试在 Dockerfile 中设置它,但是到目前为止构建失败,出现了以下错误:

“ bash: nvm: command not found”

下面是我的 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 的基础知识,但是到目前为止,我所做的所有阅读都没有向我展示一个好的解决方案。

103877 次浏览

Dockerfile 中的每个 RUN都在不同的容器中执行。因此,如果您在一个容器中提供一个文件,那么它的内容在下一个容器中将不可用。

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

以你为例:

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 回答中的建议,我在 Dockerfile 中将 source 命令替换为以下命令

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

当每次在单独的进程中运行 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

我必须从这样一个事实开始: 我搜索了所有地方以获得 dockernvm的工作示例,但是没有发现任何示例。甚至这个帖子里的答案也不起作用。

所以,我花了相当长的时间,想出了一个可行的办法:

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

注意我是如何通过 apt-get安装 nodejs的。我发现有些软件包不会被安装到 docker 中,除非这样做。

这是我的工作版本

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;

得到了“ abduljibali”和“ shamisis”的帮助。

为了帮助那些正在寻找在 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"]

尝试获取问题中的 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 中运行这些内容,我不会感到惊讶。这并没有被明确指出,所以我想我会提到它,因为这是什么引起我出来时,我正在做类似的流浪汉。

自接受答案以来,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

不确定如果你将需要 nvm use上的 --delete-prefix选项-我这样做了,但这可能是一些奇怪的关于我的基础图像。

这些都不适合我,对于我的 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年的最佳答案:

# 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,这可能会把你搞砸。

更新 2020年2月20日: 如果您使用的是 debian基础映像,这个解决方案是有效的。

下面是我发现的安装 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 用户)下运行,如果在 贝壳状中运行,则将源代码 ~/. bashrc文件。

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

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

我花了一两个小时才想出最干净的方法。--登录似乎无法执行。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"]

这就是对我有效的方法(我使用的是 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>了。

2022年更新

只有一个答案把 curl 安装,但不工作的整个 Dockerfile

这里我的 Dockerfile 已经准备好复制/粘贴,其中我安装了最新的 Nvm2022版本和最新的 Ubuntu

FROM ubuntu


# nvm requirements
RUN apt-get update
RUN echo "y" | apt-get install curl
# nvm env vars
RUN mkdir -p /usr/local/nvm
ENV NVM_DIR /usr/local/nvm
# IMPORTANT: set the exact version
ENV NODE_VERSION v16.17.0
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
RUN /bin/bash -c "source $NVM_DIR/nvm.sh && nvm install $NODE_VERSION && nvm use --delete-prefix $NODE_VERSION"
# add node and npm to the PATH
ENV NODE_PATH $NVM_DIR/versions/node/$NODE_VERSION/bin
ENV PATH $NODE_PATH:$PATH
RUN npm -v
RUN node -v

木头

enter image description here

笔记

  • 设置 nodejs 的确切版本是强制性的,因为如果设置 nvm use v1616.17.0将被下载,那么就没有办法从 V16获得要在 PATH 中设置的 16.17.0
  • Nvm 强制我们搜索最后和特定的版本 raw.githubusercontent。.脚本的/nvm/0.39.1/install.sh 其自述文件 https://github.com/nvm-sh/nvm#install--update-script具有如下内容: raw.githubusercontent。./nvm/最新的/install.sh
  • 如果您的 nodejsapp 是经典和标准的,不要使用 nvm,而是直接使用 FROM node:16
  • 您可以在基本映像不是 节点: 16的其他项目中使用这个 nvm 代码片段。例如,我有一个 python docker 映像,并且需要 nodejs。

2021年2月25日 主要的问题是使用“ source”指令,它是 bash shell 特有的。 在 Ubuntu18的安装中,我用‘ source’替换了‘ source’。 我的档案:

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

当扩展图像“ php: 7.4.15”(debian: buster-Slim)时,这会安装 nodejs 的 lts-version:

# 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

nvm not found可能是为不同于执行容器的用户安装的。您可能需要在安装前加上执行容器的自定义用户的前缀。最后一个 USER语句定义容器用户。

USER $USERNAME


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

原因

深入到 nvm安装脚本,例如 0.39.1,可以看到它被安装到当前用户的 $HOME中。如果您没有更改它,则 ubuntu映像的默认用户是 root。但是,当使用不同的用户启动容器时,不会找到 nvm; 因此要确保安装和执行的用户对齐。

nvm_default_install_dir() {
[ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm"
}

我真的很难让 NVM 在基于高山的图像上正常工作。我最终只是从一个官方的 Node 高山映像中复制了一堆共享目录。目前看来效果不错。

# Dockerfile


###############################################################################
# https://docs.docker.com/develop/develop-images/multistage-build/
# Builder Image
# This image is intended to build the app source code, not to run it.
###############################################################################
FROM node:16-alpine as builder


WORKDIR /build-tmp


COPY ./dist/src/yarn.lock .
COPY ./dist/src/package.json .
RUN yarn install --production


###############################################################################
# Execution image
# Nothing from the builder image is included here unless explicitly copied
###############################################################################
FROM osgeo/gdal:alpine-normal-3.4.2


# It's seemingly very difficult to build a specific version of node in an Alpine linux
# image, so let's copy node from the builder image into this execution image!
COPY --from=builder /usr/lib /usr/lib
COPY --from=builder /usr/local/share /usr/local/share
COPY --from=builder /usr/local/lib /usr/local/lib
COPY --from=builder /usr/local/include /usr/local/include
COPY --from=builder /usr/local/bin /usr/local/bin


...


CMD ["node", "main"]


在测试了这里的大部分信息以及其他文章之后,我发现这个问题和许可问题有关,这会导致一些奇怪的 bug,比如除非以 root 用户身份运行,否则不能安装 npm 项目。我的设置是沿着 PHP CMS 运行 VueJs,最后一部分是:

ENV NVM_DIR $TMP_STORE/nvm
ENV NODE_VERSION 16.15.0


RUN chown -R www-data:www-data /var/www/


USER www-data
RUN export XDG_CONFIG_HOME=$TMP_STORE \
&& curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash


#RUN chown -R www-data:www-data $NVM_DIR


RUN 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 npm install -g @vue/cli \
&& npm install -g vue


USER root

可以找到整个 Docker 配置 给你

下面是我最近使用的一个解决方案:

# Install nvm/Node.js
ENV NVM_VERSION=0.39.1
ENV NODE_VERSION=16.17.1
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v$NVM_VERSION/install.sh | bash
RUN bash --login -c "nvm install $NODE_VERSION"


# Do whatever with nvm
RUN bash --login -c "nvm use $NODE_VERSION && npm [...]"

2022年最新情况:

基于 https://stackoverflow.com/a/60137919/2047472我想出了:

FROM python:3.10


RUN touch .profile


SHELL ["/bin/bash", "--login", "-i", "-c"]
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
SHELL ["/bin/bash", "--login", "-c"]


RUN nvm install
RUN node -v
RUN npm -v
  • 如果您使用 .nvmrc并使用 source 初始化 nvm,那么要小心 nvm.sh 中的 臭虫,当 .nvmrc出现在当前目录或父目录中时,它会以返回码3退出
  • 我必须触摸 .profile,因为它不存在,否则在后续的 RUN 命令中不会激活 nvm
    • touch .bashrc不起作用