Nvm: Documentation for use in Docker container

Created on 3 May 2017  ·  15Comments  ·  Source: nvm-sh/nvm

Not sure if using NVM in a Docker container is best practice, but should be the fastest way to get both npm and node installed? (Fastest if you don't use FROM node:7 or whatever, because you use a different image - a common scenario is needing both Java and Node, in my experience, so you have to pick, either FROM java or FROM node).

I have this in a Dockerfile

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
ENV NVM_DIR "$HOME/.nvm"
RUN [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"   # exits with non-zero code
RUN nvm install 6
RUN nvm use 6

but the problem is that the third line exits with non zero code and I do not know why

Most helpful comment

@ORESoftware - I actually ended up just installing Node directly (old fashion way ;) ), I saw something funky that I didn't have time to debug this morning, for sake of discussion and helpful PR

  • build is successful
  • nvm is on the container
  • node version files added stat /bin/versions/node/v8.0.0/ and its really there
    but nvm's reference to node is "broken" after jumping in the container

Test Dockerfile:

FROM ubuntu:14.04

RUN apt-get update
RUN apt-get -y install curl
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash

RUN . /root/.nvm/nvm.sh && nvm install v8

Build Image:
docker build -t test:node_nvm .

Enter Container:
docker run -it --name "jimmy" test:node_nvm bash

Run: (nvm ls)

root@44a98d6fc128:/# nvm ls
            N/A
node -> stable (-> N/A) (default)
iojs -> N/A (default)

nvm loss reference to node

More Info:

root@49f3abde31c4:/# env | grep -Ei "nvm|home|path|term"
NVM_RC_VERSION=
NVM_CD_FLAGS=
TERM=xterm
NVM_DIR=/root/.nvm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/root

Image should of had:

root@118f68c41ac4:/# nvm install v8 && nvm ls
......
default -> v8 (-> v8.0.0)
node -> stable (-> v8.0.0) (default)
stable -> 8.0 (-> v8.0.0) (default)
iojs -> N/A (default)
lts/* -> lts/boron (-> N/A)
lts/argon -> v4.8.3 (-> N/A)
lts/boron -> v6.10.3 (-> N/A)

i'll circle back on a solution a little later

All 15 comments

Since $HOME is just /root

then I have this:

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
RUN . /root/.nvm/nvm.sh
RUN nvm install 6
RUN nvm use 6

But for some reason, nvm is not recognized at the command line, so nvm install fails.

by the way I much prefer

source nvm.sh

instead of

. nvm.sh

I have been and will continue to rail against (stupid) shorthand for the rest of my life :)

Once I change it to source, it says the source command is not recognized...so maybe something about Docker may make this not feasible?

. is more portable than source, the one is not simple shorthand for the other in all shells.

Is your docker running a login shell? I don't use docker, so I'm not sure. What shell is it using?

yeah that makes sense regarding . vs. source.

Docker uses

/bin/sh -c

to execute commands

ok. so that's normal sh (which doesn't have source at all, so you must use .).

You'd need -/bin/sh -c or /bin/sh -c --login, iirc, to get a login shell.

Separately, does docker open a new shell for every "RUN" command? if so, you'd need to source nvm.sh in any command that uses nvm.

ah yes, maybe that's the case, let me try it

In addition:
I went down the same path as @ORESoftware in setting ENV and separate RUNs

Tested and Worked:

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
RUN . /root/.nvm/nvm.sh && nvm --version

👍

Simple Note in the README.md on "Documentation for use in Docker Image" would save anyone a few minutes and be pretty helpful.

I will submit a PR for this

@ORESoftware - I actually ended up just installing Node directly (old fashion way ;) ), I saw something funky that I didn't have time to debug this morning, for sake of discussion and helpful PR

  • build is successful
  • nvm is on the container
  • node version files added stat /bin/versions/node/v8.0.0/ and its really there
    but nvm's reference to node is "broken" after jumping in the container

Test Dockerfile:

FROM ubuntu:14.04

RUN apt-get update
RUN apt-get -y install curl
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash

RUN . /root/.nvm/nvm.sh && nvm install v8

Build Image:
docker build -t test:node_nvm .

Enter Container:
docker run -it --name "jimmy" test:node_nvm bash

Run: (nvm ls)

root@44a98d6fc128:/# nvm ls
            N/A
node -> stable (-> N/A) (default)
iojs -> N/A (default)

nvm loss reference to node

More Info:

root@49f3abde31c4:/# env | grep -Ei "nvm|home|path|term"
NVM_RC_VERSION=
NVM_CD_FLAGS=
TERM=xterm
NVM_DIR=/root/.nvm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/root

Image should of had:

root@118f68c41ac4:/# nvm install v8 && nvm ls
......
default -> v8 (-> v8.0.0)
node -> stable (-> v8.0.0) (default)
stable -> 8.0 (-> v8.0.0) (default)
iojs -> N/A (default)
lts/* -> lts/boron (-> N/A)
lts/argon -> v4.8.3 (-> N/A)
lts/boron -> v6.10.3 (-> N/A)

i'll circle back on a solution a little later

good work yeah I think it's important to have clear directions on how to use NVM in Docker. Many people will use FROM X where is X is not node...and in that case will need any easy way to install node.js on the image, especially 1 particular version with Node.js...thus NVM.

@webguywalker I'm seeing the same problem, the nvm install during the Dockerfile build doesn't seem to "stick" once you hop inside the container. Did you find a solution?

@maackle - hey looked at it and just realized it was installing in an undesired directory

Step 6/7 : RUN . /root/.nvm/nvm.sh && nvm install v8 && which node
 ...
/.nvm/versions/node/v8.9.4/bin/node

Setting the NVM_DIR sorted it out
ENV NVM_DIR=/root/.nvm

chose "/root" only because this is test, use at your own discretion

Sample Dockerfile

FROM ubuntu:xenial

RUN apt-get update
RUN apt-get -y install curl
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash

ENV NVM_DIR=/root/.nvm
RUN . /root/.nvm/nvm.sh && nvm install v8

Note:

use at your own discretion
This is just an example Dockerfile, I personally would add add nvm as a user/group and then add root to the group or the user running the main processes the "box". Here is a start for keeping nvm locked down in terms of permissions

cc: @ORESoftware @maackle

Yes I had the same problem @webguywalker! And I used the same solution. I wonder if there's a better way than hardcoding the home directory but maybe not.

@maackle - I was close but couldn't figure it out

Roadblocks:

  • ${PATH} doesn't really expand well in the Dockerfile
  • NVM dynamically updates the the PATH to switch node version

As far as I was able to get:

  1. got suck on the ENTRYPOINT & CMD
  2. even tried to update .bashrc
FROM ubuntu:xenial

RUN apt-get update
RUN apt-get -y install curl

# Add user "nvm" as non-root user w/ sudo privileges
RUN useradd -ms /bin/bash nvm
RUN echo 'nvm ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
USER nvm
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash
ENV NVM_DIR=/home/nvm/.nvm
RUN . /home/nvm/.nvm/nvm.sh && nvm install v8 && which node && ls -alh /home/nvm/.nvm/
RUN ls -alh /home/nvm/.nvm/

# Add Desired user to `nvm` group
USER root
RUN adduser root nvm

ENTRYPOINT ['/bin/bash', '-c', '. /home/nvm/.nvm/nvm.sh']
#RUN echo ". /home/nvm/.nvm/nvm.sh" >> /root/.bashrc
Was this page helpful?
0 / 5 - 0 ratings