Como instalar o nvm no docker?


101

Estou no processo de construção de uma nova imagem Docker e estou tentando instalar o NVM para que possa gerenciar nodejs.

Lendo os documentos sobre como instalar o NVM, eles mencionam que você precisa fornecer seu arquivo .bashrc para começar a usar o NVM.

Tentei configurar isso em um Dockerfile, mas até agora a construção falhou com o erro:

"bash: nvm: comando não encontrado"

Aqui estão as linhas relevantes do meu 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"

Aqui está o resultado da tentativa de construir:

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

Eu sou muito novo no Docker, então posso estar perdendo algo fundamental para escrever Dockerfiles, mas até agora todas as leituras que fiz não me mostraram uma boa solução.


11
Não é uma duplicata, pois isso é específico para a instalação dentro do docker e não é uma instalação padrão
David Ficociello

Já que você está instalando apenas uma única versão do node, parece desnecessário instalar o nvm. Os Dockerfiles fornecidos pelo repositório de nós do Docker podem ser usados ​​como uma referência de como instalar o nó.
mikwat

Respostas:


121

Quando você RUN bash...cada vez que é executado em um processo separado, nada definido no ambiente não é mantido. É assim que eu instalo 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

para acelerá-lo duas vezes, basta alterar v0.20.0parav0.24.1
itsnikolay

8
com nvm 0.31.0e node, v4.2.3o caminho é/usr/local/nvm/versions/node/v4.2.3/bin
cwhsu

4
@thiagoh Isso não explica por que a instalação do nvm pelo questionador não funciona e as respostas funcionais funcionam. Não tem nada a ver com shells em execução em processos separados. É porque a questão tenta originar o bash.rc para carregar o arquivo nvm.sh que carrega o comando nvm no bash, mas o bash.rc sai mais cedo quando executado de forma não interativa, então o comando nvm não é carregado. Todas as respostas bem-sucedidas se originam de nvm.sh diretamente, em vez de via bash.rc. Esta é a chave para fazer este trabalho.
tobuslieven

2
Em vez de substituir sh por bash, você pode simplesmente fazer . $NVM_DIR/nvm.sh, evitando o binário de origem.
Razvan Grigore

3
Este está fechado, mas os caminhos precisam de um pequeno ajuste, devem ser: 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

Para ajudar a todos que procuram uma maneira de instalar o Node.js com NVM no Ubuntu (última versão), fiz o dockerfile abaixo. Estou usando a última versão do Docker, Ubuntu, Node.js e o NVM está funcionando corretamente (o $ PATH foi corrigido). Estou usando isso em um ambiente de produção.

$ 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
o NODE_PATH não deve ser ENV NODE_PATH $ NVM_DIR / versions / node / v $ NODE_VERSION / lib / node_modules
Sentient

Olá @Sentient! Estou executando este docker em um ambiente de produção (ubuntu) e dev local (OSX), ambos estão funcionando corretamente, sem erros. Você pode estar executando um NVM desatualizado?
danilodeveloper

Existe uma razão para eu usar o SUDO para instalar o build-essential e o libssl-dev? Não sou um DevOps experiente.
a.barbieri de

1
A chave ésource $NVM_DIR/nvm.sh && nvm install $NODE_VERSION
Vladimir Kornea

24

Os caminhos do nvm foram alterados desde a resposta aceita, portanto, se você quiser usar uma versão do nvm mais atualizada, precisará fazer algumas alterações. Além disso, não é necessário remapear shpara que funcione:

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

Não tenho certeza se você precisará da --delete-prefixopção no nvm use- eu precisava, mas isso pode ser algo estranho na minha imagem base.


1
Salva-vidas! Se eu tivesse visto sua resposta 3 horas atrás.
Adrian Marinica

Funcionou para mim, imagem base php: 7.1.1
Toby Mellor

18

Cada RUN um em um Dockerfile é executado em um contêiner diferente. Portanto, se você originar um arquivo em um contêiner, seu conteúdo não estará disponível no próximo.

É por isso que quando você instala um aplicativo e precisa realizar várias etapas, deve fazê-lo no mesmo container.

Com o seu exemplo:

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, muito obrigado pela explicação. Portanto, modifiquei meu script para ficar assim: `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 "] ADD files / nginx.conf / etc / nginx / EXPOSE 22` Recebo o seguinte erro: `/ bin / bash: /root/nvm_install.sh: / bin / bash: mau intérprete: Arquivo de texto ocupado `
David Ficociello

Este erro deve estar vinculado à sua linha RUN ["/bin/bash", ...]. Não deve ser circundado por [...]e não é necessário especificar o intérprete /bin/bash -c.
Kuhess

17

Isso é baseado na principal resposta e funciona em 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

Observe que nvmnão é um comando bash, é um alias. Isso pode atrapalhar você, se você estiver contando com isso $PATH.


15

Atualização 20/02/2020 : Esta solução funciona se você estiver usando uma debianimagem de base. Se você estiver usando ubuntu, veja esta resposta .

Esta é a maneira mais limpa de instalar nvmque encontrei:

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

Explicação

  • A primeira linha define o shell padrão do Dockerfile para um shell de login bash . Nota: isso significa que todos os subseqüentes RUN, CMDe ENTRYPOINTserão executados sob o usuário atual (geralmente root) e fornecerão o arquivo ~ / .bashrc se executado na forma de shell .

  • A segunda linha é instalada nvmcom bash. Quando o script é executado com bash, ele é anexado ao arquivo ~ / .bashrc .

  • A terceira linha instala uma versão particular de nodejs e a usa. Os nvm, npme nodecomandos estão disponíveis, porque eles são executados através de um shell de login bash (ver linha 1).


1
Muito obrigado !
Gaui

Interessante que isso estava funcionando para você. Tentei algo semelhante e tudo parecia bem durante as compilações, mas o NPM não foi encontrado quando fui executar a imagem resultante. A configuração explicitamente NVM_DIR(como mostrado em várias das outras respostas) corrigiu para mim.
esmail

1
@esmail que é estranho, porque os primeiros RUNconjuntos de comandos NVM_DIRem ~/.bashrc.
Dominic Roy-Stang

1
@ DominicRoy-Stang, ponto válido. A imagem com a qual estava trabalhando usa she, portanto, ignora .bashrc. Além disso, você .bashrctem certeza de que é realmente fornecido antes de executar os RUNcomandos? Em meu breve teste com a bashimagem oficial , parecia que não.
esmail

1
@esmail é o SHELLendereço da primeira linha (a instrução). Faz com que os comandos RUN consecutivos usem um shell de login que origina o .bashrcarquivo. Nota: só funciona se os comandos forem executados no modo shell, por exemplo. RUN nvm --version. Não funcionará se os comandos forem executados no modo exec, por exemplo. RUN ["nvm", "--version"]. Atualizei o link que forneci para o formulário de shell para tornar isso mais óbvio.
Dominic Roy-Stang

10

Com base na sugestão na resposta de @Kuhess, substituí o comando de origem pelo seguinte em meu Dockerfile

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

8

Aqui está minha versão de trabalho

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;

Recebeu ajuda das respostas de @abdulljibali e @shamisis.


Obter o ~/.nvm/nvm.sharquivo era a chave de que precisava.
Stephane de

Esta foi a única solução que funcionou para mim com o contêiner ubuntu 16.04.2.
drohm

7

Devo começar com o fato de que procurei por toda parte para obter um exemplo funcional de nvmdentrodocker e não encontrei nenhum. Mesmo as respostas neste tópico não funcionaram.

Então, passei um bom tempo e descobri um que funciona:

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

Observe como eu instalei o nodejsvia apt-gettambém. Descobri que alguns pacotes não são instalados dentro do docker a menos que isso seja feito.


sim - cara - tentei cerca de 100 soluções e só a sua funciona - 10x!
srfrnk

Corrija o uso de ~ / .nvm / nvm-tmp.sh, para que as versões do nó sejam instaladas corretamente dentro do diretório ~ / .nvm
guidoman

7

Uma diferença fundamental entre a tentativa de obter o comando nvm na questão:

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

que não funciona e a tentativa de fazer o mesmo na resposta aceita:

source $NVM_DIR/nvm.sh

É que a segunda versão origina o script nvm.sh diretamente, enquanto a original tenta fazê-lo por meio do arquivo .bashrc.

O arquivo .bashrc tem uma linha inicial que sai se estiver sendo executado em um shell não interativo:

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

Portanto, nunca chega ao ponto em que teria originado o nvm.sh, o que realmente coloca o comando nvm em seu shell.

Eu não ficaria surpreso se o docker estivesse executando essas coisas em um shell não interativo. Isso não tinha sido explicitamente apontado, então pensei em mencioná-lo, pois foi o que me surpreendeu quando estava fazendo algo semelhante com o vagrant.


Obrigado por encontrar a origem do problema. Copiei o arquivo /etc/skel/.bashrc da imagem base do ubuntu 19.10 e comentei as linhas ofensivas acima. Então, em meu Dockerfile, usei o comando COPY para copiar um /etc/skel/.bashrc "corrigido" para / etc / skel e somente depois disso usei RUN para criar usuários com / bin / bash como seu shell. Então, as chamadas subsequentes para RUN ["/ bin / bash", "-c", "-l", YOUR_COMMAND [S] _HERE] funcionaram bem.
Stephan Doliov

6

Levei uma ou duas horas para descobrir a maneira mais limpa de fazer isso. --login não parece executar .bashrc, então você deve fornecer -i para iniciá-lo no modo interativo. Isso faz com que o Docker grite com você um pouco, então eu só inicio dessa forma para a instalação e, em seguida, redefino para o meu shell padrão.

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

Sua resposta me fez perceber que a minha não funciona ubuntucomo imagem base (mas a sua sim). Eu estava usando debianimagens baseadas. Não tenho certeza do que está causando a discrepância entre os dois. Alguma ideia?
Dominic Roy-Stang

Estou usando o Ubuntu 19:10 como imagem base. Vou postar todas as instruções relevantes do Docker para que você tenha uma ideia do que funciona para mim. Todas as instruções que deixei de fora não são relevantes ou não posso fornecer. Vou representá-los com um comentário. Vou postá-lo no próximo comentário, pois o limite de caracteres é definido muito baixo
user2896438

4

Nada disso funcionou para mim, para meu python3-onbuildcontêiner, tive que forçar a criação de links simbólicos para a instalação do 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

Acordado. Ao instalar em um contêiner docker (Debian GNU / Linux 9 (stretch)), nvm acaba chegando $HOME/.nvmpara mim também.
Dave Stevens

Sim, links simbólicos foram necessários para adicionar a mim também. Estou me perguntando como os outros nem mesmo precisam disso.
PEZO

0

Isso é o que funcionou para mim (estou usando o 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"]

Agora você deve ser capaz de fazer nvm install <version>.


0

Apenas uma resposta coloca a instalação curl, mas não funciona em todo o Dockerfile

Aqui está meu Dockerfile pronto para copiar / colar no qual instalo a última versão do nvm 2020 com 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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.