How to install and use nvm in Docker containers for Node development

Now, if you’ve been living under a rock or just haven’t bothered with this yet, let me explain what NVM is and why its awesome:

NVM allows you to easily switch between different versions of Node on your machine without having to mess around with global installations. This means that you can have multiple projects using different versions of Node without any conflicts or issues. It’s a game-changer for anyone who works on more than one project at a time, trust me!

But what if we want to use NVM inside Docker containers? Well, bro, thats where things get really interesting (and also kind of confusing).

First off, let’s create a new directory for our Node.js app and initialize it with npm:

# Create a new directory for our Node.js app
mkdir awesome-app
# Move into the newly created directory
cd awesome-app
# Initialize the directory with npm and accept all default values
npm init -y
# Create a new file named index.js to serve as the entry point for our app
touch index.js

Now, let’s create a new Dockerfile that will install NVM and set up our environment:

FROM node:14-alpine # specifies the base image to be used for the container, in this case, the latest version of Node.js 14 on Alpine Linux
RUN apk update && \ # updates the package repository and installs the necessary dependencies for NVM and Node.js
    apk add --no-cache build-base git curl npm # installs build tools, git, curl, and npm without caching the downloaded packages
WORKDIR /app # sets the working directory for the container to /app
COPY package*.json ./ # copies the package.json file from the local directory to the /app directory in the container
RUN npm install -g nvm # installs NVM globally inside the container
RUN nvm install 14.x # installs Node.js version 14.x using NVM
USER node # sets the user to "node" for security purposes
COPY . /app # copies all files from the local directory to the /app directory in the container
WORKDIR /app # sets the working directory to /app
CMD ["npm", "start"] # specifies the command to be executed when the container is run, in this case, it will start the application using npm

Let’s break this down:

– We start by using the `node:14-alpine` image as our base. This is a lightweight version of Node that uses Alpine Linux, which means it has fewer dependencies and takes up less space in your Docker images.

– Next, we update our package manager (APK) and install some necessary tools like `build-base`, `git`, `curl`, and `npm`. We also copy over our project’s `package*.json` file so that we can use it inside the container.

– Then, we download and install NVM globally using `nvm install 14.x`. This will allow us to switch between different versions of Node without having to mess around with global installations on our host machine (which is a huge time saver).

– Finally, we set up our environment by changing the working directory to `/app`, copying over our project files, and setting the command that should be run when the container starts.

Now, let’s build and run this Docker image:

# This script builds and runs a Docker image for a Node.js project.

# Build the Docker image with the tag "awesome-node"
docker build -t awesome-node .

# Run the Docker container with the specified tag and start the project using npm
docker run --rm -it awesome-node npm start

Let’s break this down:

– We first build our Docker image using the `build` command. This will create an intermediate container that contains all of our changes, and then commit them to a new image with the tag name “awesome-node”.

– Next, we run our newly created image using the `run` command. This will start a new container based on our image, and execute the specified command inside it (in this case, `npm start`). We also add some flags to remove the container when it’s done running (-rm), and keep it interactive (-it) so that we can see what’s going on.

You now have a Docker image with NVM installed inside it, which means you can easily switch between different versions of Node without having to mess around with global installations or create multiple containers for each version.

Hope this helps! Let me know if you have any questions or suggestions in the comments below.

SICORPS