Introduction

Containers are portable and atomic units of deployment which are bundled with dependencies and pre-installed with toolchain required to run the application. A container is an instances of an Image and can represent an application, web, database or other services. A container engine is used for communication between containers and underlying kernel of Operating System. Docker is the most popular container engine. There are other container engines available as well like rkt and lxc.

Containerization with Docker

To containerize an application with Docker, we need to create a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession. 

In this blog, we will use a sample NodeJs application to demonstrate Containerization. The structure of the basic app will be:

app/
— server.js
— package.json

Server.js:

const express = require(‘express’);

const app = express();

app.get(‘/’, function (req, res) {
   res.send(‘Hello World!’);
});

app.listen(3000, function () {
   console.log(‘Example app listening on port 3000!’);
});

Package.json:

{
 “name”: “hello-world”,
 “version”: “1.0.0”,
 “description”: “Hello world app taken from: https://expressjs.com/en/starter/hello-world.html”,
 “main”: “server.js”,
 “scripts”: {
   “test”: “”,
   “start”: “”
 },
 “repository”: {
   “type”: “git”,
   “url”: “git+https://github.com/coderise/hello-world.git”
 },
 “author”: “”,
 “license”: “ISC”,
 “bugs”: {
   “url”: “https://github.com/coderise/hello-world/issues”
 },
 “homepage”: “https://github.com/coderise/hello-world#readme”,
 “dependencies”: {
   “chai”: “^4.1.2”,
   “express”: “^4.15.3”,
   “mocha”: “^4.0.1”,
   “request”: “^2.83.0”
 }
}

Dockerfile:

# The official image of the node
FROM node:boron
# ARG Version to define app version
ARG VERSION=1.0.0

# Create app directory inside image
WORKDIR /usr/src/app

# Set required environment variables
ENV NODE_ENV production

# Install app dependencies by copying package.json to image
COPY package.json .

# For npm@5 or later, copy package-lock.json as well
# COPY package.json package-lock.json ./

RUN npm install

# Bundle app source
COPY . .
# It will start the app on 3000 port of the container
EXPOSE 3000
CMD [ “npm”, “start” ]

Make sure that Docker is pre-installed on the machine. You can refer this link to install Docker. 

The Dockerfile consists set of commands which includes making work directory where necessary files will be copied. Installing dependencies using npm.  Note the base image node:boron is official image from NodeJS and it consists stable npm version. After copying all files and installing dependencies exposing 3000 port of the container and first command will run npm start.

This is sample Dockerfile. More customization is available with Dockerfile.For more in depth information please check official guide of the Docker for creating Dockerfile.

To create the images from the Dockerfile docker cli is used. Now the app structure is:

app/
— server.js
— package.json
— Dockerfile

Build the image:

$ sudo docker build -t helloworld:1.0 .

It will build the image and tag it with helloworld:1.0 here 1.0 is the version of image. By default the latest version of the image will be selected. 

This will download all dependencies to run the app. After successful build, check the image:

sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
helloworld          1.0                 c812ebca7a95        About a minute ago   678 MB
node                boron               c0cea7b613ca        11 days ago          661 MB

To run the container docker run command is used. It’s necessary to bind the  node port to container port.

sudo docker run -it -p 3000:3000 helloworld:1.0

Here its binding port 3000 to container port 3000.

Check if app is running:

$ curl localhost:3000
Hello World!

Tag image to latest or a specific version which will be stored in DockerHub. DockerHub is the central registry for storing docker images. 

$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
helloworld          1.0                 c812ebca7a95        3 hours ago         678 MB
node                boron               c0cea7b613ca        11 days ago         661 MB
$ sudo docker tag helloworld:1.0 helloworld:latest
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
helloworld          1.0                 c812ebca7a95        3 hours ago         678 MB
helloworld          latest              c812ebca7a95        3 hours ago         678 MB
node                boron               c0cea7b613ca        11 days ago         661 MB

Login to dockerhub:

(Notice: If you don’t have a DockerHub account, please visit https://hub.docker.com and create an account)

$ sudo docker login with your Docker ID to push and pull images from Docker Hub. If you don’t have a Docker ID, head over to https://hub.docker.com to create one.
Username (kubejack): kubejack
Password:
Login Succeeded
$ sudo docker tag helloworld:latest kubejack/helloworld:latest
$ sudo docker push kubejack/helloworld:latest
The push refers to a repository [docker.io/kubejack/helloworld]
50c9a7dd83b6: Pushed
94df5aea4989: Pushed
e7158264ab54: Pushed
54e9e4999177: Pushed
7c966bc7c94e: Mounted from library/node
c3031c131aac: Mounted from library/node
7df250eb9e5c: Mounted from library/node
e9591a63b7e4: Mounted from library/node
d752a0310ee4: Mounted from library/node
db64edce4b5b: Mounted from library/node
d5d60fc34309: Mounted from library/node
c01c63c6823d: Mounted from library/node
latest: digest: sha256:952ff7e89547e157630be120126a3e1d8717d45e0df72a1f49901c2bcde74250 size: 2838

This should push the Image to DockerHub from where it can be fetched and deployed to any environment.

Leave a Reply

Your email address will not be published. Required fields are marked *