8

Currently, the DDEV web container does not come with nvm (node version manager). How can I add and use it via the DDEV config.yaml file?

Michael Anello
  • 119
  • 1
  • 6

4 Answers4

13

In current ddev v1.19+ nvm is installed by default, and can be used with ddev nvm, so you don't have to do any of this. See docs. So do ddev nvm install 12 for example. If you want to bake this into the config.yaml you might want to add something like this:

hooks:
  post-start:
  - exec: nvm install 12
  - exec: cd somepath && npm install

---- Original answer below ------

I recommend using the .ddev/web-build/Dockerfile approach, as it doesn't cost you every time you do a ddev start; it just builds one time in each project (and when you upgrade ddev).

Place this file in .ddev/web-build/Dockerfile:

ARG BASE_IMAGE
FROM $BASE_IMAGE

ENV NVM_DIR=/usr/local/nvm
ENV NODE_DEFAULT_VERSION=v6.10.1

RUN curl -sL https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh -o install_nvm.sh
RUN mkdir -p $NVM_DIR && bash install_nvm.sh
RUN echo "source $NVM_DIR/nvm.sh" >>/etc/profile
RUN bash -ic "nvm install $NODE_DEFAULT_VERSION && nvm use $NODE_DEFAULT_VERSION"
RUN chmod -R ugo+w $NVM_DIR

Change NODE_DEFAULT_VERSION to what you'd like it to be. You can add to this to use all the features of nvm; you could install more than one version, and use nvm use <otherversion> in a post-start hook if you wanted to.

For more about how to use and install nvm, see the README.

For more about how to use ddev's add-on Dockerfile capability, see ddev docs on add-on Dockerfile

For details about Dockerfile syntax, see Docker's Dockerfile reference

nvm is actually shell aliases, so it isn't available in the container to non-interactive commands by default. So it works fine inside ddev ssh but doesn't work out of the box in a post-start hook. To use it in a post-start hook you can do something like this:

hooks:
  post-start:
    - exec: 'bash -l -c "nvm install v12.15.0 && nvm use v12.15.0"'
rfay
  • 9,963
  • 1
  • 47
  • 89
  • What I don't get yet: why does `ddev ssh; nvm ls;` does as expected, while the "direct call" with `ddev exec nvm ls` returns an error: `bash: nvm: command not found`? – Urs May 25 '20 at 09:22
  • 1
    `ddev exec` just runs bash, without any context, it doesn't load anything else. nvm is kind of a bash alias setup, it's dependent on getting loaded into your shell environment, so in this case is dependent on /etc/profile being run. – rfay May 25 '20 at 21:16
  • 1
    NODE_DEFAULT_VERSION is a better name for the environment variable (although it doesn't change the functionality). I changed it, thanks for the suggestion. – rfay May 25 '20 at 21:18
  • Regarding the ddev exec point: should we then simply ssh into the container to run such things (actually, I have the same issue for foundation watch, be it via a web command or ddev exec)? Or should I keep trying? – Urs May 26 '20 at 06:31
  • 1
    I prefer `ddev ssh` because it's faster and smoother when you're doing more than one thing in the container. The reason there's a difference here is that nvm is pretty much integrated into the shell as an alias or something. I'm no expert on nvm; there may be other ways. – rfay May 27 '20 at 12:47
  • 1
    Great! I kind of thought I HAD to make sure commands could be executed from outside. Good to hear it‘s also fine to just ssh in. Thanks! – Urs May 28 '20 at 05:45
3

With the help of @greggles and @heddn on the #ddev Slack channel (on the Drupal Slack workspace), I got it working with the following post-start hook:

hooks:
 post-start:
   - exec: curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
   - exec: rm -f ../.nvmrc && export NVM_DIR="$HOME/.nvm" && source "$NVM_DIR/nvm.sh" && nvm install 8.11.1 && nvm use 8.11.1

This installs nvm then sets node to version 8.11.1

-mike

Michael Anello
  • 119
  • 1
  • 6
  • 1
    I added a Dockerfile answer above (https://stackoverflow.com/a/61934500/215713) which doesn't end up costing so much time on every `ddev start`. – rfay May 21 '20 at 12:28
  • 1
    I suggest using a dedicated docker build file, instead of using post-start. This hook is executed every time you boot up your environment. A modification of the container will only be executed again when you destroy the container. – Armin Jul 14 '21 at 16:45
3

After using @rfay solution above for installing specific version of Node, I created a custom command in .ddev/commands/web which allows me to run any nvm command in the container without having to ddev ssh.

#!/bin/bash
## Description: Install or use node.
## Usage: nvm [flags] [args]
## Example: "nvm use or nvm install"
source /etc/profile && nvm $@
2

Another potential solution would be to add it to the .ddev/web-build/Dockerfile as the DDEV documentation suggests here: https://ddev.readthedocs.io/en/stable/users/extend/customizing-images/#adding-extra-dockerfiles-for-webimage-and-dbimage

Ryan McVeigh
  • 161
  • 5
  • Dockerfile needs to be capitalized... Could you please add the full details as in Mike's example? – rfay Dec 06 '19 at 20:49