---
# System prepended metadata

title: 'DevOps Training Session 4: Docker'
tags: [devops, research, reliable]

---

# DevOps Training Session 4: Docker
###### tags: `devops` `research` `reliable`

Hello btb my blog, today i will make some lab relate about to setup docker and try to make project with docker through docker_script and docker compose to bunch up all image into one, Hope you enjoy it --> [:coffee:](https://drive.google.com/file/d/1kmv_2zlP1xY9MOoRFSvibVOBLAYqib8G/view?usp=sharing)

1. Write a Dockerfile that:
- Use alpine as the base image
- Set working directory as /app
- Install git, zip, curl
- Install NodeJS via NVM (node version must be parameterized)

==> **I have some problems with nvm-nodejs-npm on export the PATH --> solution is: Try to get nodejs and npm from CDN of alpine --> Make it successfull**

```
FROM alpine:latest 

WORKDIR /app

# Get the require package
RUN apk add -U curl bash ca-certificates openssl ncurses coreutils python3 make gcc g++ libgcc linux-headers grep util-linux binutils findutils git zip

# Create a folder for storage nvm
RUN mkdir /usr/local/nvm

# Init version for pass through parameter by command
ARG version=${verison}

# Show what version is apply
RUN echo ${version}

# export env for install nvm
ENV NVM_DIR /usr/local/nvm

ENV NODE_VERSION ${version}

#### Runable but path for export have smt wrong !! ####
#======================================================================================
# Install nvm with node and npm
# RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash \
#     && . $NVM_DIR/nvm.sh \
#     && nvm install $NODE_VERSION \
#     && nvm alias default $NODE_VERSION \
#     && nvm use default

# ENV NODE_PATH $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules
# ENV PATH      $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
#======================================================================================

# Check the version input and apply package for specically option 12 or 14
RUN if [[ ${version}=="12" ]]; then apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/v3.12/main/ nodejs npm; fi

RUN if [[ ${version}=="14" ]]; then apk add --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/v3.14/main/ nodejs npm; fi

# check the node and npm install into that one
RUN node --version
RUN npm --version
```

2. Write a Powershell script and a Bash script that build the above Dockerfile into several images (must tag the image):
- Node 14 image
- Node 12 image

Bash:
```
#!/bin/bash

# read -p "Which node image do you want to work: " version

if [[ $1 != "12" && $1 != "14" ]]
then
    echo "$1 is not supported"
    exit 1
else
    docker build -t nodejs:lastestv$1 --build-arg version=$1 .
fi
```
Powershell:
```
#!/usr/bin/pwsh 

param(
    [string]$version
)

# $version = Read-Host -prompt "What version of node you want to apply"

if ($version -eq "12" -or $version -eq "14")
{
    docker build -t nodejs:lastestv$version --build-arg version=$version .
}
else
{
    Write-Host "$version is not supported"
}
```
![](https://i.imgur.com/5GNqnnw.png)

3. Write a Dockerfile that:
- Uses Node 14 image above
- Clone this repo https://github.com/johnpapa/node-hello into the
working directory
- Build project
- Run test only when the container is started
- Be able to access the web from the host machine

Dockerfile:
```
FROM nodejs:lastestv14

# Clone git hub repo to work dir
RUN git clone https://github.com/johnpapa/node-hello.git /app

#  Build Project 
RUN npm install

# Expose port for enable access port 3000
EXPOSE 3000

#  RUN Project
CMD ["npm", "start"]
```
Run Command
`docker build -t <name_image>:<tag> PATH`
`docker run -d --name <name> -p <localport>:<dockerport> <nameimage>`
Example
```
docker build -t nodejs:node_hello /home/xeusnguyen/DevOps_OrientTrainningSession/Node_project_hello/
docker run -h nodejs_hello -p 3000:3000 nodejs:node_hello
```
![](https://i.imgur.com/EjTKi2g.png)

4. Write a Powershell script and a Bash script that run the above Dockerfile (must set the container name) then check if the local web server is running

Bash
```
#!/bin/bash

# Access to Dockerfile [Folder contain that] --> Path specify
read -p "where of docker file you want to executable: " dkfilepath

if [[ -d $dkfilepath ]]
then
    read -p "which name you want to apply in container: " namecontainer
    docker build -t nodejs:node_hello $dkfilepath
    docker run -d --name $namecontainer -p 3000:3000 nodejs:node_hello
    $(timeout 1 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/3000')
    if [[ $? -eq 0 ]]
    then
        echo "Accesible into web docker"
    else
        echo "Not accesiable into web docker"
    fi
else
    echo "$dkfilepath is not a folder --> Make sure this it folder and contain Dockerfile you want to execute"
fi
```
Powershell
```
#/usr/bin/pwsh

$pthdkfile = Read-Host -p "Which path contain dockerfile"
if (Test-Path -Path $pthdkfile)
{
    $containername = Read-Host -p "Which name you want to apply for container"
    docker build -t nodejs:node_hello $pthdkfile
    docker run -d --name $containername -p 3000:3000 nodejs:node_hello
    $connection = New-Object System.Net.Sockets.TcpClient("127.0.0.1", "3000")
    if ($connection.Connected)
    {
        Write-Host "Accesible into web docker"
    }
    else {
        Write-Host "Not accesiable into web docker"
    }
}
else
{
    Write-Host "$pthdkfile is not a folder --> Make sure this it folder and contain Dockerfile you want to execute"
}
```
5. Write a Powershell script and a Bash script that run a script inside the web container to check if the Node app is running

Bash
```
#!/bin/bash

read -p "name container of web page: " namecontainer

result=$(docker exec -it $namecontainer curl 127.0.0.1:3000 || set -e)

if [[ $result ]]
then
    echo "The container can accesible inside --> Return from container $result"
fi
```
Powershell
```
#!/usr/bin/pwsh

$nameContainer = Read-Host -prompt "What name of container"

$result = docker exec -it $nameContainer curl 127.0.0.1:3000
if ($result -ne "")
{
    Write-Host "Docker can accesible inside and it return for us is $result"
}
```

6. Write a Powershell script and a Bash script that remove all containers and images

Bash
```
#!/bin/bash
docker stop $(docker ps -aq)

docker rm $(docker ps -aq)

docker rmi $(docker images -aq)
```

Powershell
```
#!/usr/bin/pwsh

docker stop $(docker ps -aq)

docker rm $(docker ps -aq)

docker rmi $(docker images -aq)
```

7. Create a docker-compose.yaml file that:
- Contains 2 services, a Node 12 app, and a Node 14 app. Using Dockerfiles and images above
- Create an index.js similar to this file but change the message
- Override the index.js in the Node 12 app with the above index.js

Docker-compose file
```
services:
  nodejs12-web:
    build:
      dockerfile: /home/xeusnguyen/DevOps_OrientTrainningSession/Node_project_hello_v12/Dockerfile
      context: .
    ports:
      - '3000:3000'
  nodejs14-web:
    build:
      dockerfile: /home/xeusnguyen/DevOps_OrientTrainningSession/Node_project_hello_v14/Dockerfile
      context: .
    ports:
      - '3001:3000'
```

8. Write a Powershell script and a Bash script that compose the above docker-compose.yaml file then check if the local web servers is running 

Bash:
```
#!/bin/bash

# Create node12
cd Node_create || exit
./bash_node.sh 12

# Create node14
./bash_node.sh 14

# Return create a 2-web node12 vs node14 with docker compose
cd .. || exit
docker-compose up --build --detach

# Check the server is exist
echo "=========================================================="
echo "=================Status Container Below==================="
echo "=========================================================="
$(timeout 1 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/3000')
if [[ $? -eq 0 ]]
then
    sleep 2
    result=$(curl -L 127.0.0.1:3000)
    echo "Server is running in port 3000, and return this message $result"
else
    echo "Server is not running in port 3000"
fi
$(timeout 1 bash -c 'cat < /dev/null > /dev/tcp/127.0.0.1/3001')
if [[ $? -eq 0 ]]
then
    sleep 2
    result=$(curl -L 127.0.0.1:3001)
    echo "Server is running in port 3001, and return this message $result"
else
    echo "Server is not running in port 3001"
fi
```

Powershell
```
#!/usr/bin/pwsh

# Create node12
Set-Location Node_create
./pwsh_node.ps1 -version 12

# Create node14
./pwsh_node.ps1 -version 14

# Return create a 2-web node12 vs node14 with docker compose
Set-Location ..
docker-compose up --build --detach

# Check the server is exist
Write-Host "=========================================================="
Write-Host "=================Status Container Below==================="
Write-Host "=========================================================="
$connection = New-Object System.Net.Sockets.TcpClient("127.0.0.1", "3000")
if ($connection.Connected)
{
    Start-Sleep 2
    $result=curl -L 127.0.0.1:3000
    Write-Host "Server is running in port 3000, and return this message $result"
}
else
{
    Write-Host "Server is not running in port 3000"
}
$connection = New-Object System.Net.Sockets.TcpClient("127.0.0.1", "3001")
if ($connection.Connected)
{
    Start-Sleep 2
    $result=curl -L 127.0.0.1:3001
    Write-Host "Server is running in port 3001, and return this message $result"
}
else
{
    Write-Host "Server is not running in port 3001"
}
```

## Conclusion
## Reference
[Docker-Doc](https://docs.docker.com/)
[Different btw CMD vs Entrypoint vs RUN  ](https://techmaster.vn/posts/36513/su-khac-biet-giua-run-cmd-va-entrypoint-trong-dockerfile)