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