Deploying a Node.js Docker container to Heroku

In the last post titled Developing Node.js applications in Docker, we have seen how we can work with Docker as our development environment.

In this post, we are going to take the app that we have built named docker-node-app and deploy it to Heroku as a Docker container.

The sample code used in this post can be found here: docker-node-app.

So, let’s get started.

Setup Heroku

The first thing we need to do is download and install Heroku tool belt on our local machine.

Download Toolbelt

You can follow the instructions given here: Install Heroku Toolbelt to install Heroku tool belt for your Operating System.

Setup Account

If you do not have a Heroku account, you can signup here.

Login

Now that we have Heroku installed, we will login. Open a new command prompt/terminal and run

Next, we need to login to the container registry. Run

Once we have successfully logged in to Heroku & Heroku container registry, let’s work with Docker.

Setup Docker

The first thing we are going to do is download Docker for our Operating System.

Download

To Install Docker on our machine, navigate to here & download the software for your OS.

Test Download

Once Installed, you can open up a command prompt/terminal and run  docker ps and you should see something like

At this point, we have both Docker as well as Heroku installed on our machine.

Next, we are going to containerize our app and deploy it to Heroku.

Setup docker-node-app

If you have not already done, please go through Developing Node.js applications in Docker, where we see how to develop Node.js applications using Docker. We are going to begin at the ending of that post.

Clone docker-node-app

Now, we are going to clone docker-node-app from https://github.com/arvindr21/docker-node-app. From anywhere on your machine, run

And then  cd docker-node-app .

Fix Port

We need to make a change to the Dockerfile  to fix the port. While deploying to Heroku, port would be assigned by Heroku.

Open Dockerfile  and update it as shown below

That is it, we are all set to deploy our awesome container app to Heroku.

Deploy to Heroku

Now, we are going to deploy to Heroku. We are going to follow the below steps

  1. Heroku create new app (one time)
  2. Heroku container push – Create and push the container to Heroku Container Registry
  3. Heroku container release – Release/run the container app
  4. Heroku open – Launch the app

From inside  docker-node-app run

This will create a new Heroku app.

Next, we will push the container

Now, we will run the container

And finally open the deployed app run

And we should see

Voila! Our Node.js that we have containerized while development is now deployed to Heroku with ease.

Development & Deployment simplified!

PS: I am shutting down the above Heroku app, as it does not have any thing specific to showcase.

Hope you got an idea as to how we can deploy Node.js containerized application to Heroku.


Thanks for reading! Do comment.
@arvindr21

Developing Node.js applications in Docker

In this post, we are going to look at developing a Node.js application using Docker as the development environment.

Why Dockerize my development?

You may ask, what is wrong with my current setup? Why should I “Dockerize my Node app”?

Well for starters, your development environment need not be the machine on which you are coding.

Let’s say that you are new to a project and you are getting started with your environment setup and you are installing an awesome plugin like grunt-contrib-imagemin and you find that its dependency libpng is missing on your machine. You Google and try to solve the problem yourself because a. you are the new member in the team and you want to prove yourself and b. you don’t know anyone in the team yet.

Everything is good so far, you were able to fix the libpng issue and now you run npm install  again and you notice that grunt-yellowlabtools needs phantomjs and for some reason the download fails while installation. Again for the above said reasons, you are too shy to approach someone so you spend the first day on the project installing the dependencies and finally setting up your environment and running your project successfully.

Very productive day one.

Now, imagine, one your first day, all you would need to do is

  1. Install Docker
  2. Run docker run -it -p 3000:3000 myproject/my-app:0.1.0

And voila, the app is running on your machine. And you are all set to get started. How about that?

4 reasons why?

Here are a few reasons why you need a “Dockerized” development environment:

  1. Your production environment will almost always never be same as your development environment. So you can directly work on your production environment setup on your local to avoid “surprising” deployment issues.
  2. Easy for your devops team to work and scale with containers in higher environments than your local
  3. One developer machine can run multiple (Node.js) applications in an isolated way
  4. Docker compose lets us run dependent pieces of softwarer in an micro service architecture easily

Now that you feel it is a good idea to Dockerize your development environment, lets look at how.

How to Dockerize a Node.js app?

We are going to follow below steps

  1. Setup Docker
  2. Build a simple Node.js application
  3. Build a Docker image
  4. Create a container from the Image and start developing.

Before we actually get started, let’s look at what is Docker.

What is Docker?

Docker is a computer program that performs operating-system-level virtualization also known as containerization.

To understand the above jibber-jabber, take a look at this video

Quite a simple and powerful concept.

If you would like to dig deeper in the world of containers, checkout this playlist from Vmware

Now that we understand the why, what and how; let’s get our hands dirty by building a Dockerized Node.js app.

Getting Started

First we are going to install Docker

Install Docker

For this tutorial, we are going to use Docker Community Edition (CE). To Install Docker on our machine, navigate to here & download the software for your OS.

Once Installed, you can open up a command prompt/terminal and run  docker ps and you should see something like

The above output shows that there are no images running.

Now, lets quickly test drive Docker.

Run  docker run busybox echo "hello from busybox"  and you should see that the busybox image downloaded locally and run the echo command that we have provided. The output would be as follows.

Now that we got the Docker installation done & verified, let’s move on.

Build a Node.js App

Now, we will setup a simple Node.js app. If you are planning to run this application on your local machine, make sure Node.js is setup on your machine. You can follow this post Hello Node. I am using the following versions

If you are going to run the app directly in a docker container, you can skip local installation of Node.js.

Anywhere on your machine, create a folder named  docker-node-app and open a new terminal/prompt there.

First, we are going to initialise a new Node.js project. Run

This will create a package.json  with default contents. Update it as shown below, as applicable

Do note that I have added a script named  start, which launches the app that we are going to create in a moment.

Now, we are going to build a simple app, which prints the environment variables on the machine it is running.

Inside docker-node-app folder, create a file named index.js  and update it as shown below

All we are doing is iterating the  process.env object & building a string with the key and value.

Test drive the Node.js application

Let’s test the application we have built. You can do this only if you have Node.js installed on your machine.

You can simply run

or

If you do not have nodemon on your machine, you can install it as follows

Once the server is up and running, navigate to http://localhost:3000/, we should see

Isni’t very brave of me to publish my machine’s environment variables out in public :/ 

Now that we have validated that the app is working fine, lets “containerize” it.

Build a Docker image

Now that we have our sample app running, let’s create an image. Inside docker-node-app  folder, create a file named Dockerfile and update it as shown below

On line 2 : we set the base image in which our app is going to run. Which is a Node image with version 8 installed.

On line 8: we create a directory where our source code would reside in the container

On line 11: we switch to the working directory

On line 15: we copy our current source code to the image

On line 18: we install nodemon globally.

On line 21: we install any other dependencies defined in  package.json

On line 24: we expose port 3000 so the host machine can access the app

On line 27: we start the Node.js app on boot of the container

Simple right?

Now to make sure we copy only what we need, we will create a file named  .dockerignore at the root of  docker-node-app and update it as shown below

Now that we are done with setup, we will build the docker image. From inside   docker-node-app  folder, run

docker-node-app docker build -t arvindr21/docker-node-app:0.1.0 .

Do note that  arvindr21 from the above command is my Dockerhub username. If you are planning to push this image to Dockerhub, it needs to be with your Dockerhub username.

Once the build kicks off, you should see logs as shown below

Now, if we run  docker-node-app docker images we should see

Awesome! Now our image is ready. We need to create a container from this image and voila our app  will be running from inside an image.

Create a conatiner & Run the app

This is the most important step in this process.

To run our Node.js app in a container, we are going to

  1. Download the code base on our local machine
  2. Point the volume of the container to the folder where the code is downloaded and run the image
  3. Open the local copy of code on your host machine text editor
  4. Start making changes

So, let’s move on. Since the codebase is already on our machine, we are not going to download it. If you project files are hosted on a remote server, download them to your local.

Next, we are going to create a container from the image and point the volume to docker-node-app  folder, as shown below

docker-node-app docker run -it -p 3000:3000 -v ${PWD}:/usr/src/app arvindr21/docker-node-app:0.1.0

/usr/src/app  : is the folder in the container

${PWD}  : is the folder on the host machine where the code is present. I am running the above command from the same folder, hence I am passing in the present working directory variable

3000 : is the port mapping between host machine and container.

Note: If you want to run this app as a background process pass a  -d or a deamon flag as shown below

docker-node-app docker run -itd -p 3000:3000 -v ${PWD}:/usr/src/app arvindr21/docker-node-app:0.1.0

If everything goes well, we should see

Now, navigate to http://localhost:3000/ and we should see something like

Do notice that the values now have updated to the environment variables from the container. Do notice the  HOSTNAME property, it is displaying a value of  cb0852847690. Now, from the host machine, run  docker ps and we should see something like

Do not the  HOSTNAME matches the  CONTAINER ID.

So, ya, it works.

Now to the awesome part, live reloading.

Live reload the container app

Now, we have our app running in a container and the code base on our host machine, let’s add a change to the code base on our local machine and see the changes reflect in the container app.

Open  index.js and update it as shown below

I have added a new piece of code to display the time.

Save the file on your host machine and we should see the following in the terminal/prompt

Now, back to http://localhost:3000/ and we should see

Voila! The time appear-th! Keep refreshing to see the value change.

Now, when you are done with the development, you can push the code to the remote repository and shutdown your Docker image. And once when you are ready to code, you can bring up the Docker image.

Adding code files

Okay, so we are able to make changes to an existing file, what about adding a new file. Let’s try that out.

Inside  docker-node-app folder, create a file called as  date.js and update it as shown below

All we have done is externalized the logic to get current date. Now, open  index.js and update it as shown below

And you should see a message in the prompt/terminal that the server restarted due to changes. Now if we go back to browser and refresh, we should see that the output does not change but we are loading the date from an external file.

Simple and powerful development environment that is development and deployment friendly.

You can find the code used in this post here: arvindr21/docker-node-app


Thanks for reading! Do comment.
@arvindr21