Skip to content

Instantly share code, notes, and snippets.

@remarkablemark
Last active March 18, 2025 01:08
Show Gist options
  • Save remarkablemark/aacf14c29b3f01d6900d13137b21db3a to your computer and use it in GitHub Desktop.
Save remarkablemark/aacf14c29b3f01d6900d13137b21db3a to your computer and use it in GitHub Desktop.
Install node and npm with nvm using Docker.
#!/usr/bin/env bash
# confirm docker daemon is running and connected
docker version
# build the image based on the Dockerfile and name it `nvm`
docker build -t nvm .
# confirm image is present
docker images
# enter container terminal
docker run -it nvm bash
# set the base image to Debian
# https://hub.docker.com/_/debian/
FROM debian:latest
# replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
# update the repository sources list
# and install dependencies
RUN apt-get update \
&& apt-get install -y curl \
&& apt-get -y autoclean
# nvm environment variables
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 4.4.7
# install nvm
# https://github.com/creationix/nvm#install-script
RUN curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.2/install.sh | bash
# install node and npm
RUN source $NVM_DIR/nvm.sh \
&& nvm install $NODE_VERSION \
&& nvm alias default $NODE_VERSION \
&& nvm use default
# add node and npm to path so the commands are available
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
# confirm installation
RUN node -v
RUN npm -v
@majarianilkumar
Copy link

I'm using the .nvmrc file to automatically install and use the node version, but after building my dockerfile, it is using always the Default version as default -> 18.3.0 (-> v18.3.0 *) even though using this version "v16.14.1". Could someone have any idea about this issue? please find the docker file and image building log below.

Dockerfile

FROM node:slim
RUN rm /bin/sh && ln -s /bin/bash /bin/sh 
RUN apt-get update >/dev/null \
    && apt-get install -y curl >/dev/null \
    && apt-get -y autoclean >/dev/null
ENV NVM_DIR /usr/local/nvm
RUN mkdir -p /usr/local/nvm
COPY .nvmrc .   # Copy local .nvmrc file to dockerimage, .nvmrc file contains string "16.14.1" which is the node_version i need to run 
COPY .testfile .  # this file contains deeper shell integration -->https://github.com/nvm-sh/nvm/tree/v0.39.1#bash
RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
RUN source $NVM_DIR/nvm.sh \  
            && nvm install \
            && nvm use
RUN cat .testfile >> $HOME/.bashrc
RUN source $HOME/.bashrc
RUN echo $NODE_VERSION
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/v$NODE_VERSION/bin:$PATH
RUN node -v
RUN npm -v

Building docker image log

Building Docker image for: nvm-docker-image
INFO[0000] Retrieving image manifest node:slim          
INFO[0000] Retrieving image node:slim from registry index.docker.io 
INFO[0002] Built cross stage deps: map[]                
INFO[0002] Retrieving image manifest node:slim          
INFO[0002] Returning cached image manifest              
INFO[0002] Executing 0 build triggers                   
INFO[0002] Unpacking rootfs as cmd RUN rm /bin/sh && ln -s /bin/bash /bin/sh requires it. 
INFO[0007] RUN rm /bin/sh && ln -s /bin/bash /bin/sh    
INFO[0007] Taking snapshot of full filesystem...        
INFO[0009] cmd: /bin/sh                                 
INFO[0009] args: [-c rm /bin/sh && ln -s /bin/bash /bin/sh] 
INFO[0009] Running: [/bin/sh -c rm /bin/sh && ln -s /bin/bash /bin/sh] 
INFO[0009] Taking snapshot of full filesystem...        
INFO[0009] RUN apt-get update >/dev/null     && apt-get install -y curl >/dev/null     && apt-get -y autoclean >/dev/null 
INFO[0009] cmd: /bin/sh                                 
INFO[0009] args: [-c apt-get update >/dev/null     && apt-get install -y curl >/dev/null     && apt-get -y autoclean >/dev/null] 
INFO[0009] Running: [/bin/sh -c apt-get update >/dev/null     && apt-get install -y curl >/dev/null     && apt-get -y autoclean >/dev/null] 
debconf: delaying package configuration, since apt-utils is not installed
INFO[0016] Taking snapshot of full filesystem...        
INFO[0017] ENV NVM_DIR /usr/local/nvm                   
INFO[0017] RUN mkdir -p /usr/local/nvm                  
INFO[0017] cmd: /bin/sh                                 
INFO[0017] args: [-c mkdir -p /usr/local/nvm]           
INFO[0017] Running: [/bin/sh -c mkdir -p /usr/local/nvm] 
INFO[0017] Taking snapshot of full filesystem...        
INFO[0018] COPY .nvmrc .                                
INFO[0018] Taking snapshot of files...                  
INFO[0018] COPY .testfile .                             
INFO[0018] Taking snapshot of files...                  
INFO[0018] RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash 
INFO[0018] cmd: /bin/sh                                 
INFO[0018] args: [-c curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash] 
INFO[0018] Running: [/bin/sh -c curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash] 
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 15037  100 15037    0     0   734k      0 --:--:-- --:--:-- --:--:--  734k
=> Downloading nvm as script to '/usr/local/nvm'
=> Appending nvm source string to /root/.bashrc
=> Appending bash_completion source string to /root/.bashrc
npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.
=> You currently have modules installed globally with `npm`. These will no
=> longer be linked to the active version of Node when you install a new node
=> with `nvm`; and they may (depending on how you construct your `$PATH`)
=> override the binaries of modules installed with `nvm`:
/usr/local/lib
+-- [email protected]
=> If you wish to uninstall them at a later point (or re-install them under your
=> `nvm` Nodes), you can remove them from the system Node as follows:
     $ nvm use system
     $ npm uninstall -g a_module
=> Installing Node.js version 18.3.0
Downloading and installing node v18.3.0...
Downloading https://nodejs.org/dist/v18.3.0/node-v18.3.0-linux-x64.tar.gz...
######################################################################## 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v18.3.0 (npm v8.11.0)
Creating default alias: default -> 18.3.0 (-> v18.3.0 *)
=> Node.js version 18.3.0 has been successfully installed
=> Close and reopen your terminal to start using nvm or run the following to use it now:
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
INFO[00[24](https://gitlab.com/t8822/sandbox/docker-build/-/jobs/2598875120#L24)] Taking snapshot of full filesystem...        
INFO[0035] RUN source $NVM_DIR/nvm.sh             && nvm install             && nvm use 
INFO[0035] cmd: /bin/sh                                 
INFO[0035] args: [-c source $NVM_DIR/nvm.sh             && nvm install             && nvm use] 
INFO[0035] Running: [/bin/sh -c source $NVM_DIR/nvm.sh             && nvm install             && nvm use] 
Found '//.nvmrc' with version <16.14.1>
Downloading and installing node v16.14.1...
Downloading https://nodejs.org/dist/v16.14.1/node-v16.14.1-linux-x64.tar.gz...
######################################################################## 100.0%
Computing checksum with sha[25](https://gitlab.com/t8822/sandbox/docker-build/-/jobs/2598875120#L25)6sum
Checksums matched!
Now using node v16.14.1 (npm v8.5.0)
Found '//.nvmrc' with version <16.14.1>
Now using node v16.14.1 (npm v8.5.0)
INFO[0039] Taking snapshot of full filesystem...        
INFO[0053] RUN cat .testfile >> $HOME/.bashrc           
INFO[0053] cmd: /bin/sh                                 
INFO[0053] args: [-c cat .testfile >> $HOME/.bashrc]    
INFO[0053] Running: [/bin/sh -c cat .testfile >> $HOME/.bashrc] 
INFO[0053] Taking snapshot of full filesystem...        
INFO[0065] RUN source $HOME/.bashrc                     
INFO[0065] cmd: /bin/sh                                 
INFO[0065] args: [-c source $HOME/.bashrc]              
INFO[0065] Running: [/bin/sh -c source $HOME/.bashrc]   
Now using node v16.14.1 (npm v8.5.0)
INFO[0066] Taking snapshot of full filesystem...        
INFO[0076] RUN echo $NODE_VERSION                       
INFO[0076] cmd: /bin/sh                                 
INFO[0076] args: [-c echo $NODE_VERSION]                
INFO[0076] Running: [/bin/sh -c echo $NODE_VERSION]     
18.3.0
INFO[0076] Taking snapshot of full filesystem...        
INFO[0087] No files were changed, appending empty layer to config. No layer added to image. 
INFO[0087] ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules 
INFO[0087] ENV PATH $NVM_DIR/v$NODE_VERSION/bin:$PATH   
INFO[0087] RUN node -v                                  
INFO[0087] cmd: /bin/sh                                 
INFO[0087] args: [-c node -v]                           
INFO[0087] Running: [/bin/sh -c node -v]                
v18.3.0
INFO[0087] Taking snapshot of full filesystem...        
INFO[0097] No files were changed, appending empty layer to config. No layer added to image. 
INFO[0097] RUN npm -v                                   
INFO[0097] cmd: /bin/sh                                 
INFO[0097] args: [-c npm -v]                            
INFO[0097] Running: [/bin/sh -c npm -v]                 
8.11.0

@manish-2014
Copy link

manish-2014 commented Jun 18, 2022

There is apparently an offical docker container for NVM. Here is the docker file link

I have created a Dockerfile for nvm v0.39.1 (latest today) and Ubuntu 22.04 by copying and pasting commands from the official Dockerfile into my custom container's Dockerfile

FROM ubuntu:22.04
# removed docker command for my stuff


USER ${user}

# we need a .bashrc  for install.sh to work
RUN touch ~/.bashrc && chmod +x ~/.bashrc

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

# this node version is old but I need it for my use case
ENV NODE_VERSION=12.16.1

# relevant code I pasted from above link
# nvm
RUN echo 'export NVM_DIR="$HOME/.nvm"'                                       >> "$HOME/.bashrc"
RUN echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"  # This loads nvm' >> "$HOME/.bashrc"
RUN echo '[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loads nvm bash_completion' >> "$HOME/.bashrc"


# nodejs and tools
RUN bash -c 'source $HOME/.nvm/nvm.sh   && \
    nvm install $NODE_VERSION && nvm use $NODE_VERSION && nvm alias default $NODE_VERSION       && \
    npm install -g doctoc urchin eclint dockerfile_lint && \
    npm install --prefix "$HOME/.nvm/" && \
    npm install --global gulp-cli';
 # I added gulp for my use case 

# then  the rest of the dockerfile
WORKDIR /home/${user}

# add your entrypoint
ENTRYPOINT ["path-to-my-shell-file"]

@grinsteindavid
Copy link

grinsteindavid commented Aug 25, 2022

How to install nvm in Docker / devcontainer

FROM mcr.microsoft.com/vscode/devcontainers/cpp:ubuntu-20.04

RUN mkdir /usr/local/nvm
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 14.18.1
RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/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/versions/node/v$NODE_VERSION/bin:$PATH

it worked for me

@Ihor-Kokhan
Copy link

Ihor-Kokhan commented Sep 1, 2022

grinsteindavid commented 7 days ago β€’
How to install nvm in Docker / devcontainer
FROM mcr.microsoft.com/vscode/devcontainers/cpp:ubuntu-20.04
RUN mkdir /usr/local/nvm
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 14.18.1
RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/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/versions/node/v$NODE_VERSION/bin:$PATH
it worked for me

+1 Thanks

@jonathantito
Copy link

How to install nvm in Docker / devcontainer

FROM mcr.microsoft.com/vscode/devcontainers/cpp:ubuntu-20.04

RUN mkdir /usr/local/nvm
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION 14.18.1
RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/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/versions/node/v$NODE_VERSION/bin:$PATH

it worked for me

THANKS!!!! :)

@aviadhahami
Copy link

If anyone still finding themselves wondering here, I made a working gist with the above + python2.7 for old-timer apps
https://gist.github.com/aviadhahami/910b7f51f9fd53b4a3624f888b2981c9

@AlexAtkinson
Copy link

You can add the nvm to your docker-entrypoint.sh file. This will make nvm/npm work in any login, even /bin/sh. The exception is when using the image in a multi-stage build. See below.

. "$NVM_DIR/nvm.sh"
exec "$@" # Last line

Include it like:

COPY docker-entrypoint.sh .
ENTRYPOINT [ "/docker-entrypoint.sh" ]

Images setup with NVM that are used in a multi-stage build require nvm to be setup manually.

FROM some_nvm_image

RUN \. "$NVM_DIR/nvm.sh" \
    && npm --version \
    && node --version

But don't put a lot of time on such problems. NVM is a localdev tool. If you're building for production, either use an official node docker image, or borrow their Dockerfile to build your own.

@gustavo-olegario-aba
Copy link

Man, why every time I search for K8S and Docker I ended up finding @remarkablemark in Google results? πŸ˜† Man your SEO is killer

@remarkablemark
Copy link
Author

@gustavo-olegario-aba haha thanks, does the code still work? I haven't updated it in a long time πŸ˜‚

@gustavo-olegario-aba
Copy link

@gustavo-olegario-aba haha thanks, does the code still work? I haven't updated it in a long time πŸ˜‚

It was not exactly what I was looking for, but it was worthy the time for sure

@remarkablemark
Copy link
Author

@gustavo-olegario-aba thanks as long as you had a good time, I'm good with that πŸ˜„

@sauloefo
Copy link

Here is my solution which doesn't care about version numbers but installs latest npm and node LTS, doesn't use any symlinks, doesn't mess up with $PATH and /bin/sh but uses a login shell:

FROM debian:buster

ARG DEBIAN_FRONTEND=noninteractive

SHELL ["/bin/bash", "-l", "-euxo", "pipefail", "-c"]

RUN apt-get update; \
    apt-get full-upgrade -y; \
    apt-get install -y --no-install-recommends \
        ca-certificates \
        curl \
    ; \
    apt-get clean; \
    rm -rf /var/lib/apt/lists/*

ENV NVM_DIR /usr/local/nvm

RUN mkdir -p "$NVM_DIR"; \
    curl -o- \
        "https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh" | \
        bash \
    ; \
    source $NVM_DIR/nvm.sh; \
    nvm install --lts --latest-npm

RUN command -v nvm; \
    command -v node; \
    node --version; \
    command -v npm; \
    npm --version

Thanks to https://www.theguild.nl/nvm-in-docker/ to show a more elegant way by using a login shell.

This one worked to me. Thanks @bheisig !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment