Firstly, let’s have a quick understanding of docker and container then will move on to the building of a node app in the docker container.
What is Docker?
Docker is a tool designed to make it easier to create, deploy and run an application using containers. Containers help the developer to package up the whole application (including its dependencies, libraries and other things it needs to run the application) as one package.
Docker is a bit like a virtual machine. But unlike a virtual machine, rather than creating the whole virtual operating system, Docker allows applications to use the same Linux kernel as the system they are running on. This gives the application a significant performance boost and reduces the size of the application.
Docker benefits both developer and system administrators, by making it the part of DevOps (Developer + operations) toolchain. So, developers can focus on writing code without worrying about the system that it will ultimately be running on.
What is a Container?
Container contains applications in a way that keep them isolated from the host system they are running on. Containers allow a developer to package up the application with all its parts it needs, such as libraries and other dependencies, and ship it all as one package. And they are designed to make it easier for developer and system administrator to push their application code from dev environment to a staging or production environment in a fast and replicable way. In a way, containers behave like a virtual machine. To the outside world, they can look like a complete system.
Here’s is a list of docker commands
docker run
- Runs a command in a new container.docker start
- Starts one or more stopped containers.docker stop
- Stops one or more running containers.docker build
- Builds an image from the Docker file.docker pull
- Pulls an image or repository from a registry.docker push
- Pushes and image or repository to a registry.docker export
- Export a container’s filesystem as a tar archive.docker exec
- Runs a command in a run-time container.docker search
- Searches the Docker Hub for images.docker attach
- Attaches to a running container.docker commit
- Create a new image from a container’s changes.
Check out the complete list of commands in the Docker documentation
Containerization vs Virtualization
Containerization: is a lightweight alternative to the full machine virtualization that involves encapsulating an application to the container with its operating system.
Containers use the same host OS, instead of installing OS for each guest VM.
Virtualization: A virtual machine is a complete copy of the operating system, this means replication of binaries, drivers and libraries between the different VMs running on the same server and wastage of significant server resources.
Containerization provides isolation to run your application while sharing the same OS resources and on the other hand, virtualization provides the same functionality but has its own OS so VM systems can run on a different operating system and VM can host multiple applications versus a container that will normally have a single application running on it.
For example, if we have a 2 node API running on different node version it may possible if we deploy them in VM they may break but if we deploy them in containers they are completely isolated from each other.
Build Node app with Docker
Now you know what is docker and its benefits, we will build a node application with it.
Follow this guide to install Docker on your machine Docker Installation. Once you have installed docker on your machine you can move ahead.
Firstly, we are going to create a sample node application and then we will build a docker image for it, and lastly, we will instantiate a container from that image.
Create the Nodejs app
First, create a directory where all the files are gonna store. In this directory create a package.json
file that describes your app and its dependencies:
{
"name": "docker-node-app",
"version": "1.0.0",
"description": "It is a sample node application that is containerised and deployed using docker.",
"main": "index.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "4.17.1"
}
}
Install application dependencies by following command:
npm install
Then, create a app.js
file that defines a web app using Express.js framework:
const express = require('express')
const app = express()
const port = 8080
app.get('/', (req, res) => res.send('Node application containerised using docker.'))
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
Now we created the sample Nodejs application, in the next steps, we will run this application inside the docker container. First, you need to build a docker image for your application.
Create a Dockerfile
Create an empty file called Dockerfile
:
touch Dockerfile
Open Dockerfile
inside your editor.
Each Dockerfile
must begin with a FROM
instruction. The first thing we need to do is define the application’s base image, on which our application is going to build. In this case, we are using node to build our image.
FROM node:10
Next, we will create a directory inside the docker container where the application’s code is going to live, that is called working directory for the application. We create that with the following instruction:
WORKDIR /usr/src/app
This image comes with Nodejs and NPM already installed so next thing you will install the application dependencies inside the docker image. For that, you need to copy app package.json
and package-lock.json
inside the image and with the help of RUN
instruction we will do npm install
as mentioned below:
# A wildcard is used to ensure both package.json and package-lock.json are copied.
COPY package*.json ./
#Install dependencies
RUN npm install
To copy to application’s source code inside the docker image, use the COPY
instruction:
COPY . .
This app is bind to port 8080
so we’ll use the EXPOSE
instruction to have it mapped with the docker daemon.
EXPOSE 8080
Finally, we define the command to run the application using CMD
instruction which defines application run-time. Here we start our node application like this node app.js
:
# CMD command defines your app runtime.
CMD ["node", "app.js"]
Your Dockerfile
should look like this:
FROM node:10
# Create a work dir
WORKDIR /user/src/app
# Copy package.json and package-lock.json in docker container
COPY package*.json ./
# Install all the dependencies for the application
RUN npm install
COPY . .
EXPOSE 8080
# CMD command defines your app runtime.
CMD ["node", "app.js"]
Build the image
Go to the directory that has your Dockerfile
and runs the following command to build the Docker image. The -t
lets you tag your image with a name so it’s easier to find while you run docker images
command:
docker build -t <your username>/docker-node-app .
Your image will be listed by docker images
command:
$ docker images
# Example
REPOSITORY TAG ID CREATED
node 10 1934b0b038d1 5 days ago
<your username>/docker-node-app latest d64d3505b0d2 1 minute ago
Run the image
Run your image with the following command:
docker run -it -d -p 9000:8080 <your username>/docker-node-app
-d
flag runs the application in detach mode, that means running the container in the background and -p
flag redirects the public port 9000
to the private port 8080
inside the docker container.
if you wish to go inside the container, you can use the following command:
# Enter in the container
$ docker exec -it <container id> /bin/bash
To test your app, open http://localhost:9000 inside your browser.
Check out the application source code here
I hope you must have enjoyed it. I write articles like this every week, you can check those out here mountainfirefly.dev.