Install Node In Docker Container

/ Comments off

Jan 26, 2017 So, we would need to execute a command on our node container, using the run command provided by docker-compose. Docker-compose run -rm -no-deps node bash -ci 'npm install'. Note the -no-deps argument, which prevents to start db service in this case. This command would work fine. Yet, if we check nodemodules file permissions, we would get an. In this guide you will learn how to set up your own VeChain Thor node that can connect to main or test net. For this, we will be using Docker and assume you are running a Windows OS. Step 1: Install Docker Wikipedia defines Docker as An open-source project that automates the deployment of software applications inside containers by. EXPOSE: It ensures that a process running in a Docker container is listening on port 3000. It helps forward the ports from the host to the container. CMD: It executes the node app.js command inside our Docker container after the container has started. Step 2: Creating a.dockerignore file. Let’s now try and build a custom container and test it with the code. Testing It Within A Container. Let’s go back to Terminal, stop the server, and remove the node modules because they will be different for Mac OS and Linux. # ctrl + c - to stop the server rm -rf nodemodules; Now let’s create a new Docker container based on an Alpine image.

Debugging an application involves detecting and removing existing errors also known as bugs in a code which can cause it to work unexpectedly or even crash. Debugging allows the developers to find and resolve bugs or defects in the application to prevent incorrect and unwanted operations.

In this tutorial, we will build a Node.js application with a bug in it, run it in a Docker container and use Visual Studio Code debugging tools for Node.js to debug it. The tutorial can be used by developers as a reference when building their applications.

Prerequisites

To follow along with this tutorial, you are required to have the following.

  • Prior knowledge of Docker containers and Node.js.
  • Docker installed.
  • Node.js installed.
  • Microsoft Visual Studio Code installed.
  • A web browser. I will be using Google Chrome.

Step 1: Creating the root directory

We will create a simple to-do list application that allows the users to add and delete tasks. We will also introduce a minor bug when coding the application and use Visual Studio Code to address the issue and fix it.

Node

Open a new terminal window, browse to a root directory, and run the command below:

Step 2: Initializing the Node.js project

Initialize the project by executing the below command:

The above command will generate a file named package.json in the TodoApp folder. The package.json file contains the information related to the Node.js project. It also gives information to npm about the project’s dependencies.

The file will look like this:

Creating the to-do application

Next, we will build our to-do application using Express.js: a fast, popular and lightweight Node.js web framework.

Express makes the development of web applications easier.

Step 1: Installing project’s dependencies

We will install express and a few other prerequisites needed by the application by running the command below:

Step 2: Coding the app.js file

Then we will create a file named app.js in the TodoApp directory with the code below:

Step 3: Creating the todo.ejs file

Next we will create a file ./views/todo.ejs and paste the following code in it:

Step 4: Starting the web server

Start the web server by executing the command below:

A success message that the server is running and listening to the specified port will be displayed on the console window.

Creating a Docker image

Now we have successfully created a Node.js application.

Next, we will create a Docker image for it.

A Docker container is built from a Docker image that contains the necessary information needed to deploy and run the application with Docker.

To run a Docker container, we can either create our own Docker image or download an already built Docker image. In our case, we will create our own Docker image. A Docker image is comprised of multiple layers, which are a read-only file system.

Docker works in a way that it creates a layer for every instruction contained in a Dockerfile. Each new layer resides on top of the previous layers.

For the application’s code that may change often, it’s recommended to place it towards the end of the file.

Step 1: Creating a Dockerfile

Create a file named Dockerfile in the project’s root directory with the lines of code below:

Let’s take a closer look at the file we have just created:

  • FROM: Sets the base image. Everything that will be added later will be based on this image. We are going to use Node.js version 14 in this tutorial.
  • WORKDIR: The working directory for the commands COPY, RUN and CMD is set here.
  • RUN: It executes the npm install command in a Docker container.
  • COPY: It copies the files to the Docker image from the build context.
  • EXPOSE: It ensures that a process running in a Docker container is listening on port 3000. It helps forward the ports from the host to the container.
  • CMD: It executes the node app.js command inside our Docker container after the container has started.

Step 2: Creating a .dockerignore file

As we do not want to send large files to the build context and speed up the system, we use the .dockerignore file.

It is a text file similar to .gitignore which contains the name of the directories and files that should not be added to the build. The file .dockerignore will contain the following content:

Step 3: Building a Docker image

Next, we will execute the docker build command to build our Docker image:

The -t flag specifies the name of the image. The path to the context points to the set of files we want to reference from our Docker file.

As discussed earlier, the docker build command adds a new layer for every command in the Dockerfile.

Docker deletes the intermediate containers once the command executes successfully.

Step 4: Running the Docker container

With our Docker image in place, we can now run it by executing the docker run command and pass it the arguments below:

  • -p is the port on the host. In our case, we will use port 3001 that will be forwarded to the container port 3000 and separated by :.
  • -e will create an environment variable. In our case, we use the name SECRET and assign it the value to bestkeptsecret.
  • -d ensures the container will execute in the background.
  • The name of the image in this case: to-do-app.

The whole command will look like below:

Step 5: Verifying if the container is running

We can verify that our Docker container is running using:

The output will be similar to the one shown below:

Step 6: Inspecting the Docker logs

To inspect the logs, execute the docker logs command followed by the id of the container:

The output will appear as below:

Step 7: Testing the app on the web browser

Now that our application is up and running. We can browse to the link http://localhost:3001, and we try to add a new todo. As we can be seen below, the application displays an error on the line: todolist.forEach(function(todo, index) of the todo.ejs file.

In the steps below, we will look at how to debug the error above using Visual Studio Code.

Step 8: Stopping the Docker container

First, we have to stop the container from running by executing the below command:

Debugging using Visual Studio Code

Visual Studio Code comes loaded with debugging tools for the Node.js applications running inside a Docker container.

Below are the steps we can follow to use them:

Step 1: Updating the Dockerfile

Edit the Dockerfile by replacing the line below:

With:

Our updated Dockerfile will now look as shown as below:

Step 2: Editing the package.json file

Edit the package.json file by adding the line of code below:

The line of code above initializes the Node.js process to listen to a debugging client running on port 9229.

List

The updated package.json file will now look like this:

Step 3: Building the Docker image

Note that every time the Dockerfile gets updated, we must build the Docker image again:

Also, note that Docker will now run the npm run start-debug command as we updated earlier.

Step 4: Running the Docker container

To debug using Visual Studio Code, we must forward port 9229.

This is done by running the command below:

The above command will produce the following output:

Step 5: Inspecting the Docker logs

We can check the logs by running the docker logs command and specifying the id of the container as shown below:

Note that the debugger is now listening to port 9229. Next, we will configure Visual Studio Code to debug our application.

Steps when debugging the application using Visual Studio Code

Launch Visual Studio Code and open the project directory as below:

Step 1: Configuring Visual Studio Code

The debug configurations in Visual Studio Code are stored in a file named launch.json. To access it, press Ctrl+Shift+P and then search for Debug: Open launch.json and open it.

Edit the launch.json file to look like the code snippet below:

Since we do not want to go through the code in the node_modules directory and builtin Node.js core modules, we have included the skipFiles attribute.

Step 2: Placing a breakpoint to debug the code

Now that we have everything set up, we can start debugging the application. If you can recall from earlier, we had an error in the view/todo.ejs file, in which the line of code below goes over the todolist array.

In the app.js file, the todo.ejs file gets rendered at this line res.render('todo.ejs', { todolist: req.session.todolist }). We will put a breakpoint at that line and check the value of the todolist variable as shown below:

Step 3: Inserting an expression to check the value of the variable

Press Shift+Ctrl+D to change to the debug view.

Then click on the Debug and Run button as shown below:

To check the value of the req.session.todolist variable, we will insert an expression to watch. It is done by selecting the + sign under watch on the sidebar of the window and then entering the name of the variable (req.session.todolist) as shown below:

Step 4: Testing the app on a web browser

Next, switch to the web browser and refresh the page http://localhost:3001/todo as shown below:

The Waiting for localhost message will appear at the bottom left of the page, meaning that the breakpoint we created has paused execution, and we can check the value of the req.session.todolist variable.

Now move back to Visual Studio Code to get the details as shown:

So the req.session.todolist variable is undefined. Is it possible to fix the bug?

Step 5: Fixing the bug

The ejb template goes through the todolist array and ought to be placed in the current session. However, we did not initialize the array, so it is undefined.

To fix the bug we will add the lines of code below to the .use function:

The code snippet should be added just above the next function.

Our .use function will look as below:

Step 6: Stopping the Docker container

Next we will retrieve the id of our running container by executing the docker ps command as below:

Stop the container by running the docker kill command followed by its id as below:

Step 7: Re-building the Docker image

To apply the changes we made earlier, we must re-run the docker build command as shown below:

Step 8: Re-running the Docker container

Next, run the container using the command below:

Step 9: Reload the web browser to confirm if a bug is fixed

Reload the https://localhost:3001/todo page on the browser and check the results as shown below:

Wrapping up

We have successfully written a to-do list Node.js application, executed it in a Docker container, and utilized our Visual Studio Code debugging tools to identify and fix the issue.

The tutorial can be helpful to the developers who want to build their Node.js application in a Docker container and use the Visual Studio code debugging tools to debug their code.

The code snippets and files used in this tutorial can be found in this GitHub Repo.

Happy coding!

Peer Review Contributions by: Geoffrey Mungai

About the author

Verah Ombui

Verah Ombui is an undergraduate Computer Science student at Jomo Kenyatta University Of Agriculture and Technology. Her interests are web development, cloud computing, and data science. Verah is a technology enthusiast.

In this post I share with you how I set up a simple Dockercontainer for Node.js development. I’ve never found a simple tutorial for beginners that meets my needs!

My requirement is to do all development debugging in a container, so I am assured of consistent behaviour in any environment. I do not want to install Node.js or npm locally on my mac! I cannot be bothered to use a Makefile or Dockerfile to build images - this is only required in the final stage for production!

This is the first in a series of posts on my journey with containers and orchestration. The next post introduces you to Wiring up (networking) Node.js and MongoDB containers.

You’ll need to install Docker Desktop and Microsoft Visual Studio Code 1.10+ - both are available for Windows and mac OS.

To be clear, this is simply a setup for developers - this is not the way to use containers in production (i.e. please go ahead and build images with Dockerfile). In addition, I only advocate downloading 'Official' or 'Docker Certified' images off Docker Hub.

In the host (i.e. on our macOS terminal):

Create a working directory e.g. ~/Work/node and in that directory, create hello.js with:

Share the folder in Docker > Preferences... > File Sharing:

  • Add the folder
  • Hit Apply & Restart

Back in the terminal, download and run a new Node.js container. The run arguments are:

  • -it is shorthand for --interactive --tty to get the console by running the given bash shell
  • --rm to delete the container when done, since we always use the original image without persisting changes
  • -v to mount a local volume (the current folder $PWD) to the given folder in the container
  • -p to “publish” the port so the host can get to it, in this case 8080

Now the terminal will be running the shell within the container! You’ll know because the prompt will be something like [email protected]:

I prefer to specify bash or /bin/bash as the shell, because while the official node image does run bash, many other images specify an ENTRYPOINT (i.e. a specific executable or comamnd to run when the container starts) and do not run the shell!

In the container terminal, run:

Open a browser to locahost:8080 and you should get the Hello world message!

To stop the program, back in the container terminal, hit Ctrl-C.

In the container, install nodemon to monitor for changes to hello.js and automatically restart the node server.

Install Node In Docker Container

Now, you can make changes to hello.js and node will restart. Try it - make a change to the “hello world” output and refresh your browser.

Because the container above is not persistent, when you stop the container (with Ctrl-C) and re-start, the installed nodemon would be gone. So, let’s create a new image of Node.js persisting the installed nodemon.

Run the container as above but give it a name, nodedev:

In the container, install nodemon and exit (which stops the container):

At this stage you should install any other Node.js modules you need in the container, once and for all!

Now, make the change persistent in a new image called nodemondev, and then run the container again to test (note I don’t run with --name but instead use --rm again because I’m not going to persist subsequent changes):

In the container, you can type nodemon and viola! nodemon is already installed!

In addition, if you want to just immediately run nodemon but yet have the console respond to Ctrl-C to stop node (rather than have to manually stop the container), just run:

Container

VS Code is great for many reasons - one of which is that it can attach to a running Node.js instance and debug the code with step-through and breakpoints.

The important settings when starting Node.js (which in this case I do via nodemon in a container) are:

Install Nodejs In Docker Container

  • turn on debugging with --inspect=0.0.0.0:9229, where 0.0.0.0 would allow all ingress (remote connections), otherwise debugging is only available from within the container.
  • and, publish the debugging port 9229 to the host with -p 127.0.0.1:9229:9229.

Note that the Node.js Debugging guide states 'Exposing the debug port publicly is unsafe', so we mitigate by only exposing the port to only the host hence the explicit 127.0.0.1. However, port 8080 is public - but now you know how to change it if so desired.

Now, the magic from VS Code:

  • Hit the debugging icon (or from the menu View > Debug)
  • Next to the green play button, hit the dropdown and select Add Configuration....
  • In the new editor launch.json, select Attach to Process.
  • The block below will be added and you must add the remoteroot path manually (remember the comma in the preceding line). Save and close:

Without remoteRoot, you’ll get an Unverified breakpoint message whenever you try to set a breakpoint!

Now hit the green play button and you’ll be prompted to attach to a Docker container. Simply select yours:

To test, place a breakpoint at res.writeHead(200); by pressing F9, and refresh the page in your browser. You’ll suddenly be back in VS Code with variables, call stack, etc. displayed. Brilliant!

BTW, if you are too lazy to choose a process above, you could pre-configure everything. The downside is that every new container will need a section like this, where as with the above, as you can select from many containers with different debugging ports (as long as code is always in the /code folder).

You can read more about the options at Node.js debugging in VS Code.

Still want more? How about running the docker command line from the green play button in VS Code directly?

Create another debug configuration in the launch.json file as below:

Now you never have to leave VS Code, even the Terminal is embedded!

Install Nodejs On Ubuntu Docker Container

It’s really easy to use Docker containers for development, just a little bit of overhead which you can easily script. This provides a more consistent environment without having to install Node.js, etc. on your mac or Windows desktop, more so if your servers are mostly Linux-based.

Install Node In Docker Container Architecture

On to the next post, Wiring up Node.js and MongoDB containers!