Image

Build a Node.js Application with Docker

Part 1 : Quick start

Install docker

sudo apt-get update
sudo apt-get install docker.io -y
sudo docker --version

View docker version

docker -v 

Build very simple Node.js Project

I. Project structure

- node_prj_with_docker 
    |_ src /
        |_ index.ts
    |_ .dockerignore
    |_ .gitignore
    |_ Dockerfile
    |_ package.json
    |_ tsconfig.json 

src/index.ts

import express from "express";

const app = express();
const PORT = 8000;

app.get("/", async function (req, res) {
  res.send("Docker is working.");
});

app.listen(PORT, async function () {
  console.log(`App runnint on ${PORT}`);
});

Dockerfile

FROM node:latest
WORKDIR /app
COPY . /app
RUN npm install
EXPOSE 8000
CMD ["npm","start"] 

.dockerignore

node_modules
npm-debug.log
Dockerfile
.dockerignore

package.json

{
  "name": "node_with_docker",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "nodemon src/index.ts"
  },
  "dependencies": {
    "@types/express": "^4.17.17",
    "express": "^4.18.2",
    "nodemon": "^2.0.21",
    "ts-node":"^10.9.1",
    "typescript":"^4.9.5"
  }
}

Build docker image

sudo docker build -t image_name:version_number .
# Eg
sudo docker build -t vendor_name/node_with_docker:0.0.1 .

Run docker image

sudo docker container run -d --name <name_of_app> -p <local_port>:<docker_port> <image_name>:<version>
# Eg 
sudo docker container run -d --name docker_with_node -p 8000:8000 vendor_name/node_with_docker:0.0.1

Push the Image to the Docker Hub

docker login -u your_dockerhub_username 
docker push <docker_image>:<image_version>
# Eg 
docker push aanandggs/node_with_docker:0.0.1

Part 2 : Detail explaination Docker

Detail explaination Docker with Node.js example

Learn about the fundamentals of Docker, build your own Docker image, and publish it to the Docker Hub.

How Does Docker Work?

Docker provides a standardized way to develop, test, and deploy code.

You can think about Docker as a super-powered advanced virtual machine. Let’s learn more about it with an example.

Comparison between Virtual Machine and Docker

Before getting started to work on Docker, we should understand some fundamentals of how it works. They are:

  1. Docker Engine
  2. Docker Container
  3. Docker Image

What is Docker Engine?

The Docker engine is an open-source containerization technology you can use to build a containerizing application. We can use the Docker engine on a variety of platforms through Docker Desktop or Binary Installation. To simplify, the software that hosts the containers is called Docker Engine.

What is a Docker Container?

A container is a standard unit of software that packages up the code and all required dependencies needed to run an application on different platforms or computing environments.

Containers are fully isolated from the computing environment, so applications run quickly and reliably from one computing environment to another.

Docker containers are built from container images.

What is a Docker image?

A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application. It includes code, runtime, system tools, system libraries, and settings.

As we discussed, containers are built from images. Images become containers when they starts running on a Docker Engine.

Use Cases for Docker

Docker gives you the ability to run an application in any type of environment which is completely isolated from the current environment. This isolated environment is called a container.

This isolation and security allow us to run as many containers as we want in a host. Docker helps developers to work in a standardized environment using local containers which provide all the packages and dependencies to run an application.

Let's see a few use cases of Docker:

  1. Developers can write code locally and share their work using Docker containers
  2. You can use Docker to deploy your applications into a test/production environment and execute automated and manual tests
  3. When developers need to fix something, they can easily make the changes and push the Docker image to the testing or production environment

Just like Git, we can use Docker when we're making changes to our projects. If we make any changes we can just push the Docker images and pull them into the host machine. No more changes need to be done in the host server.

Here are the deployment steps you'd go through if you're not using Docker:

  1. Pull/clone the code from Git
  2. Install dependencies, run migrations, and so on in the host machine.
  3. Start the application

These steps have to be repeated on every server whether it is a testing or production environment.

Here is the deployment steps using Docker:

  1. Pull the docker image (docker pull)
  2. Run the container in the host machine (docker run)

What is Docker Hub?

Docker Hub is the largest community for Docker images. It allows you to share the container images among your team, or the Docker community. Docker Hub is sort of like GitHub. Here, Docker images reside instead of the project's code.

You can pull the open-source Docker images also. To use this you have to create an account in Docker hub.

Now that you know a bit about how Docker works and why it's useful, let's learn how to containerize an application.

How to Containerize a NodeJS Application using Docker

Prerequisites:

  1. A Basic understanding of NodeJS Applications
  2. Docker desktop application

You can install the Docker Desktop application by following their original documentation.

You can verify if Docker is installed on your machine by querying it's version like this:

docker -v

Command to check docker version

Find Docker Version

Let's start our implementation.

Instead of starting over from scratch, I have created a super simple Express API that exposes only one endpoint. I pushed the code to a public repo on GitHub. You can clone the repo by running the below command:

git clone https://github.com/5minslearn/node_with_docker.git
Clone the sample project using GitHub

This is the project's structure:

Simple NodeJS Project Structure

I have created only one endpoint ("/") and calling it will return "Greeting from 5minslearn". I've simplified this as much as possible to allow us to focus more on Docker.

How to Create a Dockerfile

Now, you'll need to create a file named "Dockerfile" in the root directory. It is the default file name for the Docker engine. Paste the following code into the file:

FROM node:latest
WORKDIR /app
COPY . /app
RUN npm install
EXPOSE 8000
CMD ["npm","start"]

Dockerfile commands to build NodeJS Project

Let's understand these commands line by line.

Defining the parent image is the first step of Docker engine. You have to define the parent image from which you're building the project. In our case it's Node.

There are a lot of parent images available in Docker Hub. You have to define the Image Variant next to the parent image. I always prefer to use the latest node image.

FROM node:latest

Define parent image from which we are building the project The second step is to define the working directory in Docker. Let's define our working directory as the app directory.

WORKDIR /app

Working directory for docker

Copy the project to the app directory. Make sure you exclude the node_modules directory. We will see how to ignore files/folders in the upcoming steps.

COPY . /app
Copy the NodeJs project to app folder

In the above command, the . indicates that all the files and directories are to be copied to the app folder.

The next step is to install the required dependencies with this command:

RUN npm install
Install dependencies using RUN command

RUN is an image build step. The state of the container after a RUN command will be committed to the container image. A Dockerfile can have many RUN steps that can layer on top of one another to build the image.

Expose the port in which application should run.

EXPOSE 8000
Expose the port in which application should run

The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime.

Finally run the execution command:

CMD ts-node src/index.ts
Command to run the Project

CMD is the command the container executes by default when we launch the built image.

Tip: I recommend that you install the Docker extension if you're using VS Code. It'll help you with its solid suggestions.

VS Code Docker extension

How to Ignore Files So They're Not Copied into the Docker Container

You have to exclude the unwanted files from being copied into the container. The .dockerignore file helps you with that. It works like .gitignore for Git.

You can define all the files you have to ignore and don't want to copy.

Using .dockerignore to exclude the unwanted files from being copied to the container Great! You've completed the Docker configuration. Let's run the application.

How to Build Docker Images

You can build a Docker image by running the docker build command. Here's the syntax for it:

docker build -t image_name:version_number .
Syntax to Build Docker Image

image_name indicates the container image name and version_number indicates the image version. Did you notice the dot (.) at the end of the command? It indicates that the Docker image should be built from the current directory.

I decided to set the image name as node_with_docker. Remember that the image name has to be prefixed with the Docker hub username. I've created my Docker hub account with the aanandggs username. So, my image name is aanandggs/node_with_docker. You may choose to enter whatever you want.

docker build -t aanandggs/node_with_docker:0.0.1 .
Command to Build Docker Image

Sample output of building docker image

Once you've built your Docker image, you'll be able to see it on your Docker Desktop.

Docker Image in Docker Desktop

How to Run the Docker Image After we build the Docker image, the next step is to run it. When an image starts running on a Docker Engine, it'll become a container.

Let's run our image which we built in the previous step:

docker container run -d --name <name_of_app> -p <local_port>:<docker_port> <image_name>:<version>
Syntax to Build Container from container image
docker container run -d --name docker_with_node -p 8000:8000 aanandggs/node_with_docker:0.0.1
Command to Build Container from container image

Docker Command to create and run a container Let's understand the above command.

We use the docker container run command to create and run a new container from an image.

The -d flag instructs the container to run in the background (detach). It prints the container id.

The --name parameter gives a name to our container.

We use the -p parameter to publish a container’s port to the host. It'll bind the port 8000 of your local machine with the port 8000 of the Docker container.

image_name:version indicates the image and its version that this container should run.

You can have a look at the running containers in the Docker Desktop app.

Running Container in Docker Desktop

The Dashboard shows that our app is running. Let's check the output on the browser by trying to access the "/" endpoint. Hit locahost:8000/ on your browser. You should see a message similar to the one in the below screenshot :

NodeJS App running output

You have successfully run an app with a Docker container.

Note: You can bind any local port to the Docker port. Ensure your local port is not used by any other process.

How to Push the Image to the Docker Hub

Create your profile on Docker Hub. Come back to terminal and run the below command to login to Docker CLI:

docker login
Command to Login to the docker

If you face any issues with login, follow this doc to login to the Dockerhub on your machine.

After a successful login, you can push the image to Docker hub.

docker push <docker_image>:<image_version>
docker push aanandggs/node_with_docker:0.0.1

Sample output of pushing image to docker Hurray! Docker images are uploaded to Docker hub.

You'll be able to see them in the Docker hub console.

Pushed Docker image in DockerHub

Since our image is public, anyone on the internet can pull the image and run it on their machines without any third-party installation.


Part 3 : Basic commands

Busic docker commands

sudo apt-get install docker.io

Getting Docker Images

sudo docker pull ubuntu
#    Or 
sudo docker pull ubuntu:latest
#    Or 
sudo docker pull ubuntu:14.04

Search docker

sudo docker search mongo

List current installed docker

sudo docker images 

Running Image in Docker Container

sudo docker run ubuntu:14.04 echo 'hello world'

Running Image in Docker container as custom name

sudo docker run -ti --name mymongo ubuntu:14.04 /bin/bash

Data Volume in Container

sudo docker run -d -v /data ubuntu:14.04
sudo docker run -d -v /var/www:/data ubuntu:14.04

# root@cef44bf69c38:/# cd data
# root@cef44bf69c38:/data# ls
# sample.txt logo.png

Enter terminal in current running docker container

sudo docker run -t -i ubuntu:14.04 /bin/bash
# root@090b21537ff8:/#
# root@090b21537ff8:/# apt-get update && apt-get install -y nodejs

Running Container as Background Service (Daemon)

sudo docker run -d -p 27017:27017 ubuntu:mongo

Log current working docker container

sudo docker ps 

Saving image update

sudo docker commit -m 'Installed NodeJS' -a 'Your name' berserk_bohr ubuntu:node

Rename docker name

sudo docker tag ubuntu:node ubuntu:nodejs 
sudo docker images 

Stop docker image

sudo docker ps --all 
sudo docker stop container_id
# Or 
sudo docker stop container_name

Start docker image

sudo docker start container_id
# Or 
sudo docker start container_name

Delete docker image

sudo docker rmi -f ubuntu:nodejs 
#   Or 
sudo docker rmi -f image_id
sudo docker images 

To stop the running application container

Using the CONTAINER ID listed in your output, stop the running application container. Be sure to replace the highlighted ID below with your own CONTAINER ID:

docker ps
docker stop CONTAINER_ID
# Eg
docker stop e50ad27074a7

List your all of your images with the -a flag:

docker images -a

Remove the stopped container and all of the images

Remove the stopped container and all of the images, including unused or dangling images, with the following command:

docker images -a

Output

REPOSITORY                                           TAG                 IMAGE ID            CREATED             SIZE
your_dockerhub_username/nodejs-image-demo            latest              1c723fb2ef12        7 minutes ago       73MB
<none>                                               <none>              2e3267d9ac02        4 minutes ago       72.9MB
<none>                                               <none>              8352b41730b9        4 minutes ago       73MB
<none>                                               <none>              5d58b92823cb        4 minutes ago       73MB
<none>                                               <none>              3f1e35d7062a        4 minutes ago       73MB
<none>                                               <none>              02176311e4d0        4 minutes ago       73MB
<none>                                               <none>              8e84b33edcda        4 minutes ago       70.7MB
<none>                                               <none>              6a5ed70f86f2        4 minutes ago       70.7MB
<none>                                               <none>              776b2637d3c1        4 minutes ago       70.7MB
node                                                 10-alpine           f09e7c96b6de        13 months ago         82.7MB
docker system prune -a

Linking container

sudo docker run -d ubuntu:mongo
sudo docker ps
#Output Name => silly_archimedes

sudo docker run -d -p 80:3000 --link silly_archimedes ubuntu:node 

To fix "Error starting userland proxy: listen tcp4 0.0.0.0:8000: bind: address already in use."

sudo docker rm id 
sudo kill -9 `sudo lsof -t -i:8000`

Ref :
How To Build a Node.js Application with Docker
How to Get Started with Docker using NodeJS


aung thu oo

#HIRE ME

OPEN TO WORK

Ko Aung Thu Oo

Having over 15 years of working experience in Laravel, PHP, Flutter, Node.Js, Vue.JS, JAVA. Strong information technology professional with a degree i...

View detail