Docker, easy start with nodejs-express app
Tags: javascript, node, docker, webdev
Published: 2021-10-13 18:36:06

![Hello Docker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m3mzhgiakhspdknm7fdc.jpg)


# Docker, what is it? how is it beneficial? how to easily use it?



### This is going to be a series of posts, this will be the first of them to explain some easy steps to start using docker containers and deploy apps with it, in this very step we are going to use [nodejs](https://nodejs.org/en/) with [express](https://expressjs.com/) framework to host a hello world app.



### So what is docker?


Docker is lovely developer tool that makes it easy to install and run software without worrying about setup and dependencies.



### How is it beneficial?


This is because it makes containers, imagine a multi layer cake where you take a verticle slice of it, so you take from each layer a portion but you don't care about the rest of the slices. Here is an illustration for it.

![Docker containers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5kocawlk41qq7h27grz.JPG)

Which makes it easy for microservices, one example that we will be seeing soon is deploying multiple services with different environemnts or maybe different versions of the very same dependency, like different nodejs versions.


### How to use it? 


This is my favorite part, where it's enough with the talking and we start to write some code!!


##### Pre-requirements:

* Installed **NodeJs**, any version and that's what is cool with docker!!
* Installed **npm**, which usually comes with Nodejs.
* Installed **Docker** for windows,linux,...etc
* Registered **Dockerhub account**, it's for free ;)  


First lets setup our server we start by initializing the folder structure
```
npm init -y
```

So you get a package.json file with initial setup.


now for express 
```
npm add express
```

add the script to the scripts part in package.json
`package.json`
```
....
  "scripts": {
    "start": "node index.js",
  },
....
```

create index.js file in the root directory


`index.js`
```
const express = require('express')

const app = express()

app.get('/', (req,res) => {
  res.send('Hello World!!')
})

server.listen(3000, () => {
  console.log(`Listening on port 3000`);
})
```

in the terminal type, `npm run start`

go to the browser and hit localhost:3000 and here it's there, 'Hello world!!'


#### So Where is docker??? Here it comes in the next steps ;)

 
in the root directory create a file **with no extension with the name Dockerfile** with the following content




`Dockerfile`
```
FROM node:alpine

WORKDIR /app
COPY package.json .
RUN npm install
COPY . .

CMD ["npm", "start"]
```

#### So What is going on???

1. `FROM node:alpine` -> is you saying to docker you want to start from an initial image that exists publicly on dockerhub, because once you go with docker you have no nodejs runtime that you have on your machine so you need this dependency.

2. `WORKDIR /app` -> this is the work directory inside the container you are making.

3. `COPY package.json .`-> here you are copying the package.json file to the work directory, please take notice the '.' context which means to copy in the context directory.

4. `RUN npm install` -> to install the required packages, in our case it's expressjs

5. `COPY . .` -> here we copy everything else to the work directory, which is the source code.

6. `CMD ["npm", "start"]` -> our start script that much match the one in the package.json

#### Right now you should be having a question, why did we copy twice, why not only one time at the end??


To answer this, I need you to wait for a second an start make use of this docker image. At this moment you have an image but you cant really use it, we need to do two things:

1. Build it
2. Push it to dockerhub

After that we can run it.

So in you terminal run the following code
```
docker build -t <your docker id>/<name of the image(eg. hello-world)> .
```
again notice the . context

now you should be seeing something like this


![Docker build](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bnwjuffjscxr9yzyv228.png)


now you have this image locally, to view all your images 
```
docker image ls
```

![Docker images](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aibgoefn3lv19k94t260.png)

now we need to make this image have its way to your hub, So in you terminal run the following code
```
docker push <your docker id>/<name of the image(eg. hello-world)>
```

Now to answer the question about copying twice in the Dockerfile configuration, this was because each command makes a layer, so we:
1.Copy the package.json file which has all the dependencies in the project
2.Install them using npm install
3.We copy the rest of the files which is the code
So whenever we make a change in the source code, only the layer that copies the code is affected and we dont install the packages again, in other words the rest of the layers are cahced.

after that you can got to your docker hub after signing in and you will find it there 


![Docker hub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j0fsx477bnyg7tl1fsqh.png)


#### Atlast, let's run this image, but notice something while running docker you can adjust the port it's listening on, so this app should be listening to **port 3000**, but we can adjust the port where it should take requests from, think of it as an **outside port**


So in you terminal run the following code
```
docker run -p 3005:3000 <your docker id>/<name of the image(eg. hello-world)>
```

Voila!!!

![Image running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r2iibt7kffd89ozhpps1.png)

go and hit `localhost:3005/`

and you should be seeing the following

![Hello world response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nhdxwb2c3phj3ac8hmr7.png)


### I hope you liked this post, I'm intending the post some other related posts (actually other parts of this series where we take it a bit harder and a bit more advanced), I'm a starter myself, so if you noticed anything that you recommend against, I'm happy to hear from you, Thanks again!!