Giter VIP home page Giter VIP logo

example_webpage's Introduction

Jenkins, Docker-in-Docker, WebHook

Thank you to Dawei for introducing Jenkins CI/CD with Docker-in-Docker
and GitHub Webhooks concept to automate above pipeline

The repository for this project is located here.

Instructions

Follow these steps to set up and run the project:

  1. Install Terraform

    Ensure Terraform is installed on your system. If not, you can follow the official Terraform Installation Guide.

  2. Provision resources

    Below command will run main.tf that provision necessary EC2 to host Jenkins.

terraform init
terraform plan
terraform apply --auto-approve
  1. Follow along the subsequent steps below to complete the entire project.

In previous 3 blogs about Jenkins we might learn about the following

Here we will elaborate more automation when changes made to pipeline script and the deployment will be triggered. We will introduce docker-in-docker concept to enable Jenkins has proper access to its own Docker Hub.

Fig 01: Switching from Container A to Container B that inherited all attributes from Container A + docker.io

First, let's see below as a necessary install during an EC2 setup found in appendix below. It is install-packages.sh file to setup EC2 with docker.

#!/bin/bash
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# make sure docker is started
sudo service docker start

# add ubuntu to the docker group
sudo usermod -aG docker ubuntu

To know docker is working, do the following or keep exit/enter terminal

ubuntu@ip-10-2-254-152:~$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
ubuntu@ip-10-2-254-152:~$

Herewith all details about docker if everything were installed properly.

ubuntu@ip-10-2-254-152:~$ docker version
Client: Docker Engine - Community
 Version:           24.0.7
 API version:       1.43
 Go version:        go1.20.10
 Git commit:        afdd53b
 Built:             Thu Oct 26 09:07:41 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.10
  Git commit:       311b9ff
  Built:            Thu Oct 26 09:07:41 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.26
  GitCommit:        3dd1e886e55dd695541fdcd67420c2888645a495
 runc:
  Version:          1.1.10
  GitCommit:        v1.1.10-0-g18a0cb0
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

ubuntu@ip-10-2-254-152:~$ docker run -p 8080:8080 -p 50000:50000 -d -v jenkins_home://var/jenkins_home jenkins/jenkins:lts
Unable to find image 'jenkins/jenkins:lts' locally
lts: Pulling from jenkins/jenkins
90e5e7d8b87a: Pull complete 
f46e108600e7: Pull complete 
67ee1cced2cb: Pull complete 
3dfb3d6cb44e: Pull complete 
46014cb180c0: Pull complete 
20f6ee282779: Pull complete 
f8ee3f626f99: Pull complete 
b636b23fb8d6: Pull complete 
a3ffaaf08d83: Pull complete 
fc8874a22e0d: Pull complete 
eef971f7a8d4: Pull complete 
fb46046a6402: Pull complete 
Digest: sha256:186a48ae298e34a21b27fe737bf0a854c3e73421ce858c4d40c403802589e23f
Status: Downloaded newer image for jenkins/jenkins:lts
3a70bf47be93251f737e94124e5a66d975f57f98c2d43a6f19bd225680c9026a

ubuntu@ip-10-2-254-152:~$ docker images
REPOSITORY        TAG       IMAGE ID       CREATED       SIZE
jenkins/jenkins   lts       41e27c2a574b   4 weeks ago   486MB

ubuntu@ip-10-2-254-152:~$ docker ps -a
CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                                                                                      NAMES
3a70bf47be93   jenkins/jenkins:lts   "/usr/bin/tini -- /u…"   28 seconds ago   Up 25 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   tender_sutherland

ubuntu@ip-10-2-254-152:~$

In this case 3a70bf47be93 is the container we are going to use now, but Jenkins won't rely on this container to access Docker. Now let's go inside it and get the jenkins Web UI password like below. Where the IP is 3.85.44.76:8080

Fig 02: Example of EC2 instance
ubuntu@ip-10-2-254-152:~$ docker exec -it 3a70bf47be93 /bin/bash

jenkins@3a70bf47be93:/$ cat /var/jenkins_home/secrets/initialAdminPassword
8af7c6b65a7f4f4e8972d7fa2928e104

jenkins@3a70bf47be93:/$

Fig 03: Example of Jenkins Web UI

Subsequent windows will ask whether you would like to chance the password. I prefer not and in case I forget the password I use the old one. In our case the Jenkins web UI access is http://35.173.177.42:8080

Fig 04: When applied immediately, Jenkins not ready to deploy Docker. See a technique below to troubleshoot.

ENABLING MAVEN IN JENKINS

There 3 java compiler in Jenkins: Maven, Gradle, Ant. Let's just pick Maven, give it a name, apply & save. Jenkins java compiler is now linked to Maven.

Fig 05: Example of Maven Setup

Installing Node.js and Python3 in Jenkins

Let's go back to the terminal pointing to container id 3a70bf47be93 again

docker exec -u root -it 3a70bf47be93 /bin/bash

and running few command below

apt update
apt install -y nodejs
apt install -y npm
node -v
npm -v
exit

Above process will take couple minutes. At the end it will show v18.19.0 and 9.2.0 for example as values of node version number and npm version.

Mounting Docker runtime into Jenkins Container (Docker in Docker)

First we will stop the current container

ubuntu@ip-10-2-254-152:~$ docker stop 3a70bf47be93
3a70bf47be93

Then we will do another command below. This command mounts volume jenkins_home, directory of docker.sock to that of Jenkins container in order to allows Docker commands within the container to communicate with the Docker daemon on the host. We should see something like below.

ubuntu@ip-10-2-254-152:~$ docker run -p 8080:8080 -p 50000:50000 -d -v jenkins_home://var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock jenkins/jenkins:lts
83d800b93e07e7086911ea4044938c1b9a5a815b8e0bbf5ef6d6678dc1f029b2
ubuntu@ip-10-2-254-152:~$ docker ps -a

CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS                            PORTS                                                                                      NAMES
83d800b93e07   jenkins/jenkins:lts   "/usr/bin/tini -- /u…"   35 seconds ago   Up 34 seconds                     0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   eager_cartwright
3a70bf47be93   jenkins/jenkins:lts   "/usr/bin/tini -- /u…"   24 minutes ago   Exited (143) About a minute ago                                                                                              tender_sutherland

-v jenkins_home://var/jenkins_home means It mounts the container "/var/jenkins_home" directory to the host machine "jenkins_home" directory. This allows persisting Jenkins data even if the container is stopped or removed.

-v /var/run/docker.sock:/var/run/docker.sock means It mounts the host machine's Docker socket to the container's Docker socket. This allows the container to communicate with the Docker daemon on the host machine.

This time we don't have to initialize a Jenkins container. All the old data is stored in Jenkins_home volume and we attached it to a new container.

Now try to access that new container 83d800b93e07.

docker exec -it -u root 83d800b93e07 /bin/bash

and install Docker client in order to run Docker commands in container. Always remember to run apt-get update to avoid error. Process below may take few a minutes to complete and change permission in order to access it and exit.

apt-get update
apt-get install -y docker.io
chmod 666 /var/run/docker.sock
exit

Access to the docker as Jenkins user

docker exec -it 83d800b93e07 /bin/bash

and do a quick test to see if docker command work in the Jenkins container

docker ps
ubuntu@ip-10-2-254-197:~$ docker exec -it 83d800b93e07 /bin/bash

jenkins@83d800b93e07:/$ docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                                                                                      NAMES
83d800b93e07   jenkins/jenkins:lts   "/usr/bin/tini -- /u…"   4 minutes ago   Up 4 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp, 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp   romantic_hoover

Docker was installed at 83d800b93e07. Both 3a70bf47be93 & 83d800b93e07 support http://3.85.44.76:8080/. Switching between them require re-login but the projects and everything else inside Jenkins UI will not be deleted.

Fig 06: Activate back 3a70bf47be93 would make http://3.85.44.76:8080/ running without Docker

Installing Python, Pip and Venv

Make sure you exit from the session above and log back in as root as below

devops@msi:~$ docker exec -it -u root 83d800b93e07 /bin/bash
root@6de04cd8225f:/# apt-get update
apt install -y python3 python3-pip python3-venv
root@83d800b93e07:/# python3 --version
Python 3.11.2
root@54676282696e:/#

Creating Credentials in Jenkins

In case that you have been logout, see password above assuming you did not change it before. Now, let's go to Dashboard → Manage Jenkins → Credentials (under Security) → Triangle beside global → Add credentials

Fig 07: How to add Credentials

You need to get token (which is called password below) from your GitHub

Fig 08: Example of Adding GitHub credentials

and you should see something like below. Remember it is your GitHub token not your GitHub password, unless it won't work.

Fig 09: Result after Adding GitHub credentials

Building a pipeline

Go to Dashboard → New Item → Enter name → Choose Pipeline. We use below repo for this pipeline https://github.com/FariusGitHub/Example_Webpage Scroll down to Pipeline Section → Click on Pipeline script → Choose Pipeline script from SCM → Click SCM → Choose Git → Enter your Repository URL → Choose your Credential

See below highlights on what to do subsequently, click apply and save.

Fig 10: Example of Adding New Pipeline with Git url

Jenkinsfile

Basically Jenkinsfile tells Jenkins what to do in Groovy syntax. There are two kinds of pipelines for Jenkins, one is called scripted pipeline, the other one is declarative pipeline.

  1. Scripted Pipeline: Most functionality provided by the Groovy language is made available to Scripted Pipeline, which means it can be a very expressive and flexible tool and it is ideal choice for power-users with complex requirements.
  2. Declarative Pipeline: Presents a more simplified and opinionated syntax. It must be enclosed with a pipeline block and it has a strict and pre-defined structure. It is friendly for beginners.

We are going to use Declarative pipeline as it is easy to get started. All we need to do is converting our workflow into code in Groovy syntax.

Jenkinsfile Reference: https://www.jenkins.io/doc/book/pipeline/syntax/

In order to enable below, credential ftjioesman has to be created first.

Fig 11: Example of Adding Docker Hub credentials

Fig 12: Result of Adding Docker Hub credentials

Once all login were setup we can run simple Jenkins Pipeline below. I started one by one from prepare, test, build, deploy stage progressively so we can see the green blocks below added as I add one stage for each build.

Fig 13: Example of Jenkins Pipeline Stage View

Triggering Pipeline Jobs Automatically with Github Webhooks

On GitHub Page, go to the repo, setting and WebHook and add the EC2 url like below with /github-webook/ endings like below

Fig 14: Web Hook Step 1 → add EC2 url in GitHub repo

Fig 15: Web Hook Step 2 → Review the saved url web hook

on Jenkins side we need to tweak the configure, Build Triggers as follow

Fig 16: Web Hook Step 3 → Check GitHub hook trigger from Jenkins Web UI

As soon as we finished making some changes in GitHub Repo above, in this case I disabled one stage the Jenkins UI starts to show some activity below. GitHub Web hook required port 80 and 443 opened which we did earlier.

Fig 17: Example of Automatic Pipeline Trigger when GitHub was edited

Fig 18: Example of Automated Update Completion

SUMMARY

Fig 20: Switching from Container A to Container B and vice versa


Container A Container B
linux command docker stop container_B_id docker stop container_A_id
docker start container_A_id docker start container_B_id
docker.io not installed installed through root (DinD)
docker ps permission denied list of active container shown

Docker in Docker (DinD) is not necessarily running container inside another container.
In this case, only one container exist at a time (as seen in docker ps). In simple terms,
Docker Inside Docker simply involves running Docker 'commands' within a Docker container.
Instead of interacting with host Docker daemon, in this case new one is spawned from old one,
providing an isolated environment for managing containers and images.

example_webpage's People

Contributors

davyzhang3 avatar fariusgithub avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.