# 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)