Trevor Trevor - 4 months ago 75
Linux Question

Bad Substitution Error Installing NVM within Debian-based Docker image

I am trying to install nvm on my Docker image. I originally thought that this Docker image was built on Ubuntu, but it is actually built on Debian. I am installing bash to curl NVM, and subsequently install node, but I get a

bad substitution
error:

Here's my Dockerfile:

FROM docker

RUN apk add --update bash \
&& touch /root/.bashrc \
&& curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.2/install.sh | bash \
&& source /root/.bashrc \
&& nvm install node \
&& npm install


I think the following error has to do with the line
&& source /root/.bashrc \


=> Downloading nvm as script to '/root/.nvm'

0
=> Appending source string to /root/.bashrc
=> Close and reopen your terminal to start using nvm
/bin/sh: /root/.nvm/nvm.sh: line 107: syntax error: bad substitution
ERROR: Service 'docker' failed to build: The command '/bin/sh -c apk add --update bash && touch /root/.bashrc && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.2/install.sh | bash && source /root/.bashrc && nvm install node && npm install' returned a non-zero code: 2


Do you see what is causing this bad substitution error, and is there a more simple way to install nvm on a Debian based Docker image? Thanks for any help.

Answer

Docker image is based out of Alpine Linux. Alpine Linux uses the default shell as sh. The error is because of the sh vs bash incompatibilities.

Unfortunately, NVM home page has instructions about Alpine Linux, but quite discouraging: nvm on Alpine Linux

After some changes, the final version that made nvm work with Alpine:

FROM docker
RUN apk add --update bash coreutils ncurses tar gzip nodejs \
  && touch ~/.bashrc \
  && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.2/install.sh | sh \
  && LINE=$(cat /root/.nvm/nvm.sh | grep -in '{BASH_SOURCE\[0\]}' | awk -F: '{print $1}') \
  && sed -i "${LINE}s/BASH_SOURCE\[0\]\}/BASH_SOURCE\}\$\{0\}/" /root/.nvm/nvm.sh \ 
  && source ~/.bashrc \
  && nvm ls \
  && nvm install node \
  && nvm use --delete-prefix v6.3.1 \
  && npm install

A little inconvenience being, you need to use the nvm use --delete-prefix v6.3.1 every time you need to work with it.

I suggest to try @BMitch's updated answer as well.