Infra/CI&CD

Jenkins CI/CD 구축 (With Docker + Github + Docker Hub)

now0204 2024. 8. 14. 16:00

 

깃허브 특정 브랜치에 push하면 jenkins가 dockerfile을 통해 이미지를 빌드하고, 이를 docker hub에 올린다

-> 이를 배포할 ec2에서 내려 받아 배포하는 과정을 다룬다. 

 

작업을 크게 설명하면,

  1. 젠킨스 다운로드
  2. 배포할 EC2에 대한 Credential 등록 - ssh agent
  3. Jenkins와 깃 허브 연동및 WebHook 등록 ( Credential 등록 )
  4. Docker hub와 Jenkins 연동( Credential 등록)
  5. 파이프라인 스크립트 작성 

 

1. 사전 작업 

 

- 배포할 EC2와 Jenkins가 다운로드 받아진 EC2에  Docker가 설치되어 있어야 한다.

- docker 설치 후 아래 명령어를 통해 docker 그룹에 user를 추가해준다

sudo usermod -aG docker 유저명

ex) sudo usermod -aG docker ubuntu

-- 만약 이래도 안되면 최후의 수단

sudo visudo 

-- nano편집기로 들어가서 제일 하단에 

ubuntu ALL=(ALL) NOPASSWD: ALL 

--위 추가

 

 

2. Jenkins 설치 

 

2.1 Swap 메모리 설정 

 

- AWS의 프리티어의 경우 메모리가 1GB라서 Jenkins가 메모리 부족으로 멈출 수 있다. 

이를 방지하기 위해 스왑메모리를 설정하자 

// swap 파일을 생성해준다. (메모리 상태 확인 시 swap이 있었지만 디렉토리 파일은 만들어줘야한다.)
$ sudo mkdir /var/spool/swap
*권한이 없으면 sudo chmod로 설정 (ex 777) 해주자
$ sudo touch /var/spool/swap/swapfile
$ sudo dd if=/dev/zero of=/var/spool/swap/swapfile count=2048000 bs=1024
// swap 파일을 설정한다.
$ sudo chmod 600 /var/spool/swap/swapfile
$ sudo mkswap /var/spool/swap/swapfile
$ sudo swapon /var/spool/swap/swapfile
// swap 파일을 등록한다.
$ sudo vim /etc/fstab
파일이 열리면 해당 파일 아래쪽에 하단 내용 입력 후 저장
- 입력 할 수 있도록 하는 명령어 -> if
- 파일 수정 후 저장하는 명령어-> esc키 누른 후 :wq 입력 후 엔터
/var/spool/swap/swapfile    none    swap    defaults    0 0
// 메모리 상태 확인
$free -h

 

 

2.2 Jenkins 다운로드 

 

- 패키지를 최신 상태로 만든다 

sudo apt update && sudo apt upgrade -y

 

- 자바를 최신버전으로 다운받는다.

java -version
sudo apt install default-jre

 

- 젠킨스를 설치해준다.

wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key |sudo gpg --dearmor -o /usr/share/keyrings/jenkins.gpg
sudo sh -c 'echo deb [signed-by=/usr/share/keyrings/jenkins.gpg] http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt update
sudo apt install jenkins

 

- 젠킨스를 실행한다.

sudo systemctl start jenkins.service
sudo systemctl status jenkins

 

이제 EC2IP:8080을 접속하면 젠킨스에 접속할 수 있다. 

 

2.3 젠킨스 초기설정 

 

위 화면이 보이면

sudo cat /var/lib/jenkins/secrets/initialAdminPassword

 

위 명령어를 통해 나온 값을 복사해서 붙여넣는다. 

 

그러면, 아래와 같이 젠킨스에 가입할 수 있다. 

 

URL은 기본 EC2의 URL로 둔다.

 

* 커스텀은 기본으로 한다


3. EC2에 접속하기 위한 Credential 설정 

 

3.1 SSH agent 플러그인 설치 

 

Jenkins 관리 → Plugin Manager → 설치 가능 앱 → SSH Agent 검색 및 설치

출처: https://lordofkangs.tistory.com/580

3.2 Credential 설정

 

 

Credentials탭으로 들어간다

 

도메인 클릭 

 

 

Kind: SSH username with private key를 설정 

ID와 Description은 자유롭게 등록

Username은 EC2의 username

Private key에는 ec2생성시 받은 .pom파일의 내용을 복사해서 붙여넣는다. (메모장으로 열어서 복붙)

 


4. Jenkins Github연동 

 

4.1 Personal access token 발급

 

settings -> Developer settings로 이동 

classic 키를 발급받아서 카피한다.

 

이정도만 체크해주자

 

4.2 Github 플러그인 설치

 

이제 젠킨스에서 젠킨스 관리 -> 플러그인에 들어가서 아래 플러그인을 설치 혹은 확인해야한다. 

Generic Webhook Trigger 
GitHub Integration 
GitHub API Plugin

 

위 3개의 플러그인이 설치되어있는지 확인하고 없다면, 다운받자 

 

4.3  깃허브에 접속하기 위한 Credential  설정 

 

출처: https://nginxstore.com/blog/microservices/jenkins-%EB%A5%BC-%ED%86%B5%ED%95%B4-github-ci-cd-pipeline-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0/

 

kind: Username and Password

username: 깃허브 아이디

password : 위에서 발급받은 토큰을 넣는다.

ID : 자유롭게 설정 (파이프라인 스크립트에서 사용한다는 것만 기억해두자)

 

4.4 Github 리포지토리 WebHook 설정

 

젠킨스에서 push이벤트를 확인할 리포지토리에 들어가서 WebHook을 설정한다.

 

 

트리거를 적용할 리포지토리 셋팅에 들어가서 webhooks설정한다.

 

PUSH 이벤트에 대한 hook 이벤트를 설정한다. 

http://젠킨스IP:젠킨스포트/github-webhook/로 설정해준다.


6. 젠킨스 도커허브 연동 

 

6.1. Docker Plugin 설치

 

Jenkins 대시보드 > Jenkins 관리 > 플러그인 관리 > 설치 가능 > Docker 검색 > Docker, Docker Pipeline 플러그인 설치 및 재실행

 

6.2 Docker Hub Credentials 등록

 

Jenkins 대시보드 > Jenkins 관리 > Credentials에 접속해서 Credential을 설정한다.

  • Kind
    Username with password
  • Username
    본인의 Docker Hub ID
  • Password
    본인의 Docker Hub Password
  • ID마음대로 작성해도 괜찮으나 파이프 라인에서 사용할 것임을 기억하자 

 

7. 스프링  CI/CD  파이프 라인 구성 

 

* 프로젝트 최상단에 spring프로젝트를 빌드해서 war파일로 만들기 위한 스크립트가 이미 작성되어 있어야한다.

지금에 경우 DockerFile이 다음과 같이 작성되어 있다.

# 1. Maven 빌드 단계 - jdk 11 메이븐
FROM maven:3.9.8-eclipse-temurin-11 AS build

# 2. 프로젝트 소스 복사
COPY . /app

# 3. 작업 디렉토리 설정
WORKDIR /app

# 4. Maven을 사용하여 프로젝트 빌드 (테스트 생략)
RUN mvn clean package -DskipTests

# 5. Tomcat 베이스 이미지 톰캣9에jdk11
FROM tomcat:9-jdk11

# 6. 빌드된 WAR 파일을 Tomcat의 웹앱 디렉토리에 복사
COPY --from=build /app/target/*.war /usr/local/tomcat/webapps/ROOT.war

# 7. Tomcat 실행 (기본 설정으로 이미 ENTRYPOINT가 설정되어 있음)

 

새 아이템을 등록한다.

 

 

배포할 코드가 담긴 리포지토리 주소를 기입한다.

 

 

빌드 트리거를 설정한다.

 

다음으로 스크립트만 작성하면 끝이다. 

 

pipeline {
    agent any

    environment {
        DOCKER_IMAGE_NAME = '도커허브닉네임/spring-mvc-app' // Docker Hub에 저장할 이미지 이름
        DOCKER_CREDENTIALS_ID = 'dockerHubKey' // Docker Hub 자격 증명 ID
        EC2_IP = '' // EC2 인스턴스 IP 주소
        EC2_USER = '' // EC2 인스턴스 사용자 ex ubuntu
        CONTAINER_NAME = '' // 컨테이너 이름 ex springContainer
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: '브랜치명', credentialsId: '깃허브CredentialID', url: '리포지토리주소.git'
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    dockerImage = docker.build("${DOCKER_IMAGE_NAME}")
                }
            }
        }

        stage('Push to Docker Hub') {
            steps {
                script {
                    docker.withRegistry('https://index.docker.io/v1/', "${DOCKER_CREDENTIALS_ID}") {
                        dockerImage.push("${env.BUILD_NUMBER}")
                        dockerImage.push('latest')
                    }
                }
            }
        }

        stage('Deploy to EC2') {
            steps {
                sshagent (credentials: ['aws_key']) { // 'aws_key'는 Jenkins에 저장된 SSH 자격 증명 ID
                    sh """
                    ssh -o StrictHostKeyChecking=no ${EC2_USER}@${EC2_IP} << 'EOF'
                        sudo docker pull ${DOCKER_IMAGE_NAME}:latest
                        sudo docker stop ${CONTAINER_NAME} || true
                        sudo docker rm ${CONTAINER_NAME} || true
                        sudo docker run -d --name ${CONTAINER_NAME} -p 8080:8080 ${DOCKER_IMAGE_NAME}:latest
                        
                        IMAGES=\$(sudo docker images -f 'dangling=true' -q)
                        if [ -n "\$IMAGES" ]; then
                            sudo docker rmi -f \$IMAGES
                        else
                            echo "No dangling images to remove."
                        fi
EOF
                    """
                }
            }
        }
    }

    post {
        always {
            cleanWs()
        }
    }
}

 

*스크립트에는 두가지 유형이 있는데

 1. Pipeline script는 젠킨스 웹에서 스크립트를 작성하고 관리하는 것을 의미한다.

 2. Pipeline Script from SCM은 프로젝트에서 jenkinsfile을 작성하고 관리하는 것을 의미한다.

 

*스크립트 문법 종류에는 2가지 유형이 있다.

 

 1. Declaretive Pipeline  : Groovy 문법 기반이며, 쉽게 작성 가능하다. -> 최상단에 pipeline이라고 되어 있으면 declarative 문법으로 작성된 것이다.

 

 2. Scripted Pipeline : Groovy문법 기반이며 Declarative보다 더 많은 기능을 작성가능하지만 어렵다. -> 최상단에 node 지시어가 있으면 scripted 문법으로 작성된 것이다.  

 

-이제 해당 깃허브 브랜치로 push하면 자동으로 배포된 것을 확인할 수 있다. 

 


참고자료

https://nginxstore.com/blog/microservices/jenkins-%EB%A5%BC-%ED%86%B5%ED%95%B4-github-ci-cd-pipeline-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0/

 

Jenkins 를 통해 GitHub CI/CD Pipeline 구축하기

이번 포스트에서는 Jenkins 를 통해 GitHub의 Continuous Integration/Continuous Deployment (CI/CD) 파이프라인을 구축하는 방법에 초점을 맞춥니다.

nginxstore.com

https://choco-one.tistory.com/6

 

[PROJECT] Jenkins + Docker를 활용한 배포 자동화

➡️ 배포 자동화 도입 이유 프로젝트를 진행하면서 프론트엔드 팀원이 작업한 웹 클라이언트를 디자인 팀원이 체크해야 했다. 하지만 배포과정은 새로운 기능 추가 또는 오류 수정 → 로컬에

choco-one.tistory.com

https://velog.io/@minchocopie/AWS-EC2%EC%97%90-Jenkins-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0

 

[AWS] EC2에 Jenkins 설치하기

AWS EC2 인스턴스 생성 보안그룹 설정 Jenkins가 설치될 EC2 인스턴스의 보안그룹을 설정한다. HTTP, SSH, 8080 포트에 대해서 모두 열어둔다. SSH EC2 인스턴스 생성 EC2 인스턴스의 이미지는 Amazon Linux로 설

velog.io

https://ldgeao99-developer.tistory.com/604

 

15. 젠킨스, 깃허브 웹훅을 통해 push 가 일어나면 자동 build 되도록 하기

1. 내 리포지토리에 웹훅 이벤트 발생하도록 설정 Payload URL 은 "실행중인 젠킨스서버IP번호:포트번호/github-webhook/" 으로 입력 이 웹훅의 트리거가 될 이벤트는 push 이벤트로 선택 2. 웹훅 이벤트가

ldgeao99-developer.tistory.com

https://hyeinisfree.tistory.com/23

 

[Devops] Jenkins, Docker로 Spring Boot CI/CD 구축하기

👩‍💻 CI/CD 1️⃣ 구성 요소 Jenkins Server : AWS EC2 Ubuntu 18.04 Spring Boot Server : AWS EC2 Ubuntu 18.04 Github Repository Docker Hub Repository 2️⃣ 진행 순서 Jenkins Server에 Docker 설치 Jenkins Server에 Docker를 이용하여 J

hyeinisfree.tistory.com