Docker: An Introduction and Tutorial With a NodeJS & MongoDB App
By: Jessica Trinh
Tags: Docker, Software Development, DevOps, Programming, Computer Science

This article will give you the run down of the latest container hype, Docker: what it is, why you might use it, and how you can use it to your advantage in your personal and professional development as a software engineer.

Diving In: What is Docker?

Docker is an open source containerization platform used by millions of developers and is the de facto standard to build and share containerized apps from desktop to the cloud. The purpose of Docker is to make it easier to create, deploy, and run distributed applications by using containers. It allows anyone to package an application on their laptop, which can then be run unmodified anywhere such as private or public clouds. Docker really lives up to their mantra of: “build once, run anywhere.”

We can get a better understanding of what Docker is by simply taking a closer look at their logo; we see a whale (named Moby Dock) happily carrying multiple boxes or containers on top of it. Kind of reminds you of a ship, doesn’t it?

Containers is a Docker term and refers to an application and its dependencies that are in self-contained units that can run anywhere. Important items to note about containers: they are based on a Docker image and each container instance is isolated and secure from all the others.

Think about about a box from Ikea that has all the tools and materials needed inside of it for you to build a piece of furniture anywhere you have the box. Let’s say your friend also got the same box from Ikea and it also has all the tools needed to build the item at their place. Docker containers are just like the Ikea boxes here, convenient, right?

More Docker Terms

Docker Engine: Portable, lightweight Linux runtime and packaging tool that can run on any operating system. This is what enables users to build, ship, and run container-based applications.

Docker Hub: A cloud service, similar to GitHub, that allows developers to share applications and automate workflows.

Docker Image: A read-only template for an application. These templates can be created in a Dockerfile or downloaded from Docker Hub. It provides a convenient way to package up applications and preconfigured server environments, which users can then use for their own private use or share publicly with other Docker users.

Demo: Dockerizing a NodeJS and MongoDB app

We’ll be dockerizing an existing NodeJS and MongoDB web application. You can see the full source code here. Let’s take a look at what we’re working with.

Here’s an image of the app’s file structure.

Items highlighted in orange are files associated with NodeJS and MongoDB.

Items highlighted in green are files associated with Docker that you’ll be adding to your NodeJS and MongoDB app (don’t worry, more details on this to come)!

Lastly, items highlighted in blue are CircleCI files.

With that small introduction out of the way, lets go ahead and get started!

note: if you’d like to follow along with the following steps, feel free to clone the repository and remove the green highlighted files.

Step 1: Create a file called Dockerfile, docker-compose.yml, and .dockerignore file in the project directory

The Dockerfile will look like the following:

The Dockerfile in an application includes a set of commands which will be executed to prepare the app for dockerization.

Step 2: Create docker-compose.yml file

The docker-compose.yml file will look like the following:

This file is responsible for executing our dockerized application, you can find more about the compose file here. This also allows MongoDB to run in a separate container. Without the docker-compose.yml file, you would not be allowed to orchestrate Docker images.

Container orchestration referring to the process that automates the deployment, management, scaling, networking, and availability of container-based applications.

You might also be wondering why mongo is running in a separate container. As a rule of thumb, each container should have only one concern or objective. In doing so, it makes it much easier to scale horizontally and reuse containers.

The MongoDB connection (highlighted in orange in the file structure image above) looks like the following:

Note line 5 which has been updated to access MongoDB from the docker container.

Step 3: Create .dockerignore file

Another important file to create is .dockerignore:

What we’re doing here is excluding node_modules and npm-debug.log which aren’t necessary for building Docker. By excluding these files, it helps to make the build faster and lighter.

Step 4: Build and Run

Run docker-compose build in the terminal

If you ever make changes to a Dockerfile moving forward, you should run docker-compose build again to ensure the containers have the latest code.

Afterwards, run the docker-compose up command from the top level directory for the project in your terminal.

You should see something like the following in your terminal to indicate it is successfully running:

Go to http://localhost:8080 (or your specified port) in a web browser.

Additional Info

Override Compose Files Safely

Add *.override.yml to the .gitignore file in the root of the repository. Create a docker-compose.override.yml file in order to set custom settings and override the root docker-compose.yml file. Level up your DevOps strategy by adding a docker-compose.override.sample.yml file to your repository. Make sure there are lots of comments that clearly explain which values can be customized for each developer’s environment!

Auto-Format Your Compose File

Compose files can get messy and difficult to read quickly, especially in microservice architectures. Use this handy compose_format command to check your Compose file and auto-format it based on best practices for readability.