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.