nvm
nvm copied to clipboard
Installation fails, if not using `bash` (new intended behavior)
Operating system and version:
Using a hardened Alpine container image as base image for our CI/CD container image.
nvm debug
output:
/app # nvm debug
nvm --version: v0.39.2
$SHELL:
$SHLVL: 1
whoami: 'root'
${HOME}: /root
${NVM_DIR}: '${HOME}/.nvm'
${PATH}: ${NVM_DIR}/versions/node/v14.20.1/bin:/usr/local/share/.config/yarn/global/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$PREFIX: ''
${NPM_CONFIG_PREFIX}: ''
$NVM_NODEJS_ORG_MIRROR: 'https://unofficial-builds.nodejs.org/download/release'
$NVM_IOJS_ORG_MIRROR: ''
sh: --version: not found
shell version: ''
uname -a: 'Linux 5.15.64-0-virt #1-Alpine SMP Mon, 05 Sep 2022 08:02:49 +0000 x86_64 GNU/Linux'
checksum binary: 'sha256sum'
OS version: Authorized uses only. All activity may be monitored and reported.
curl: /usr/bin/curl, curl 7.79.1 (x86_64-alpine-linux-musl) libcurl/7.79.1 OpenSSL/1.1.1l zlib/1.2.11 brotli/1.0.9 nghttp2/1.43.0
wget: /usr/bin/wget, GNU Wget 1.21.1 built on linux-musl.
git: /usr/bin/git, git version 2.32.3
grep: /bin/grep, BusyBox v1.33.1 () multi-call binary.
awk: /usr/bin/awk, BusyBox v1.33.1 () multi-call binary.
sed: /bin/sed, BusyBox v1.33.1 () multi-call binary.
cut: /usr/bin/cut, cut (GNU coreutils) 8.32
basename: /usr/bin/basename, basename (GNU coreutils) 8.32
rm: /bin/rm, rm (GNU coreutils) 8.32
mkdir: /bin/mkdir, mkdir (GNU coreutils) 8.32
xargs: /usr/bin/xargs, BusyBox v1.33.1 () multi-call binary.
nvm current: v14.20.1
which node: ${NVM_DIR}/versions/node/v14.20.1/bin/node
which iojs:
which npm: ${NVM_DIR}/versions/node/v14.20.1/bin/npm
npm config get prefix: ${NVM_DIR}/versions/node/v14.20.1
npm root -g: ${NVM_DIR}/versions/node/v14.20.1/lib/node_modules
nvm ls
output:
/app # nvm ls
-> v14.20.1 *
v16.18.0 *
v18.11.0 *
system *
default -> 14 (-> v14.20.1 *)
iojs -> N/A (default)
node -> stable (-> v18.11.0 *) (default)
stable -> 18.11 (-> v18.11.0 *) (default)
unstable -> N/A (default)
lts/* -> lts/gallium (-> v16.18.0 *)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.20.1 *
lts/gallium -> v16.18.0 *
How did you install nvm
?
ARG VERSION_NVM=0.39.2
ARG VERSION_NODE="14 16 18"
ENV NVM_NODEJS_ORG_MIRROR=https://unofficial-builds.nodejs.org/download/release
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v${VERSION_NVM}/install.sh | sh && \
NVM_DIR=${HOME}/.nvm && \
source ${HOME}/.nvm/nvm.sh && \
nvm_get_arch() { nvm_echo "${ARCH_NODE}"; } && \
for version in ${VERSION_NODE}; do nvm install --latest-npm ${version}; done
Create container image
docker build .
What steps did you perform?
I updated VERSION_NVM from 0.39.1 to 0.39.2 (Patch version change!).
Now docker build
fails: Error: the install instructions explicitly say to pipe the install script to 'bash'; please follow them
.
Changing the curl installation part from sh
to bash
solved this issue, although I want to avoid using bash
. Bash is not installed by default on Alpine and could be removed at any time from our hardened container image.
This check had been introduced with this commit: https://github.com/nvm-sh/nvm/commit/39d9a42c359df5dbf37c5000af8192f14a280b94
The commands above had been executed, after sucessfull installation with bash
.
What did you expect to happen?
Usage of sh
should still be possible, but maybe with a big warning message, that this is not the "official" way to install it.
Is there anything in any of your profile files that modifies the PATH
?
Nope.
If you are having installation issues, or getting "N/A", what does curl -I --compressed -v https://nodejs.org/dist/
print out?
/app # curl -I --compressed -v https://nodejs.org/dist/
* Trying 104.20.22.46:443...
* Connected to nodejs.org (104.20.22.46) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=*.nodejs.org
* start date: Jan 11 00:00:00 2022 GMT
* expire date: Feb 11 23:59:59 2023 GMT
* subjectAltName: host "nodejs.org" matched cert's "nodejs.org"
* issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
* SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x4001cfaa90)
> HEAD /dist/ HTTP/2
> Host: nodejs.org
> user-agent: curl/7.79.1
> accept: */*
> accept-encoding: deflate, gzip, br
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 256)!
< HTTP/2 200
HTTP/2 200
< date: Fri, 14 Oct 2022 10:20:31 GMT
date: Fri, 14 Oct 2022 10:20:31 GMT
< content-type: text/html
content-type: text/html
< last-modified: Fri, 14 Oct 2022 09:05:15 GMT
last-modified: Fri, 14 Oct 2022 09:05:15 GMT
< cache-control: max-age=14400
cache-control: max-age=14400
< cf-cache-status: HIT
cf-cache-status: HIT
< age: 2622
age: 2622
< vary: Accept-Encoding
vary: Accept-Encoding
< strict-transport-security: max-age=31536000; includeSubDomains; preload
strict-transport-security: max-age=31536000; includeSubDomains; preload
< x-content-type-options: nosniff
x-content-type-options: nosniff
< server: cloudflare
server: cloudflare
< cf-ray: 759f953908550b5f-AMS
cf-ray: 759f953908550b5f-AMS
< content-encoding: br
content-encoding: br
<
* Connection #0 to host nodejs.org left intact
Lots of things aren't installed by default on alpine, but they're required for use of nvm and/or node - all the "minimalism" of alpine seems to get erased once you add all the things your toolchain needs ¯\_(ツ)_/¯
The install script is bash-specific, so it won't work reliably on sh
. You could certainly set the BASH_VERSION
env var to a fake value before running the install script, but I wouldn't recommend it.
Coupling NVM to a specific shell is a bad idea. NVM already works for zsh on macs, why can't it support sh? Didn't it used to?
I currently can't find a documented way to install NVM in a docker image—which is a pretty common use case. This issue seems to be the limiting factor.
@robbyemmert nvm itself definitely works on sh
- the install script NEVER has worked reliably on anything but bash.
There's an official nvm docker image on dockerhub, and a Dockerfile in this repo: https://github.com/nvm-sh/nvm/blob/HEAD/Dockerfile