Trevor
Trevor

Reputation: 1414

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.

Upvotes: 1

Views: 1944

Answers (2)

VanagaS
VanagaS

Reputation: 3688

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.

Upvotes: 1

BMitch
BMitch

Reputation: 263549

FROM docker bases your image on the "Docker in Docker" Alpine image. Unless you have a special use case that requires Docker in Docker, this probably isn't the base image you want.

If you want a node image, consider using the premade node image. This is based on Debian jessie.

If you need to base your node install another version of Debian or Ubuntu, you can pick from multiple versions of those images, e.g. FROM debian:jessie.


Edit: it's pretty easy to add Docker to another image. Here are my Dockerfile entries for a Debian based image (appuser is a user added elsewhere that the container would normally run as, hence the Docker group addition):

ARG DOCKER_GID=999
USER root
RUN curl -sSL https://get.docker.com/ | sh
RUN groupmod -g ${DOCKER_GID} docker && \
    usermod -aG docker appuser

Upvotes: 0

Related Questions