Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Tags more
Archives
Today
Total
관리 메뉴

ultra_dev

Jenkins & Docker를 활용한 CI/CD(Mac os 기준) 본문

SPRING&JAVA

Jenkins & Docker를 활용한 CI/CD(Mac os 기준)

ultra_dev 2024. 2. 28. 23:40

젠킨스

: 오픈 소스 CI/CD 툴이다.

 

들어가기 앞서 잡담)

이번에 젠킨스를 사용한 이유는 일단 '무료'이기 때문이다.

예전 사이드 프로젝트 진행 때는 github actions를 써서 aws ec2에 CI/CD 작업을 진행했는데 이번엔 젠킨스를 쓰게 됐다.

 

사내 코드는 private Repository로 git 관리가 되고 있고, private repository에서 CI/CD를 구축하는 건 "조건부 무료.."

즉 제 기능을 다 쓰려면 유료라고 볼 수 있다. 물론 public repository로 만들면 그런 제한이 없는 걸로 알고 있다.

 

마침 회사 서버 pc도 여유가 있으니 무료인 젠킨스를 사용해서 CI/CD를 구축하는 건 허락을 받고 진행했다.

구축 이유는 개발 단계에서 프론트엔드와의 협업 때문이다.

 

프론트에서 작업을 할 때 기존에는 백엔드 코드를 깃허브에서 pull 받고 로컬에서 구동하면서 비효율적인 작업을 하고 있었다. 

현재는 백엔드에서 staging 브랜치에 코드를 push하면, 해당 코드가 CI 과정을 통과한 후 자동으로 서버에 배포되도록 설정했다. 이를 통해 프론트엔드 팀은 항상 최신의 백엔드 서버 환경을 사용하여 작업할 수 있게 되었다. 로컬에서 백엔드와 프론트엔드를 동시에 실행할 필요 없이, 서버에 배포된 최신 백엔드를 대상으로 작업하고 테스트할 수 있어 작업 효율성이 향상 됐다.

 

4~5월 중으로 Aws ECS를 활용한 클라우드로 마이그레이션 예정인데, 그때는 아마 AWS 서버를 대상으로 CI/CD를 다시 구축해야 할 것 같다.


 

Jenkins CI/CD 작업 (회사에서는 다른 방식으로 진행, 아래는 Mac os에서 젠킨스 실행 및 배포 방식)

(Mac os 기준이다. 윈도우 서버는 더 쉽다. port나 도커 경로같은 환경 설정을 해줄 필요가 없기 때문에..)

 

 

전체적인 프로세스

1. Mac os Local에서 Jenkins 실행
2. github에 push
3. Jenkins에서 CI/CD 작업 진행(깃 클론 -> 빌드 -> 도커 이미지 빌드 -> 도커 배포)

 


 

1.

젠킨스 설치 : 공식홈페이지 (https://www.jenkins.io/)

 

2. 

맥 기준으로 공식 홈페이지에서 다운로드 누르면 밑에와 같이 나온다.

간편하게 brew install 하면 된다..!

 

3. 

설치 완료 되고 http://localhost:8080/ 로 접속하면 아래와 같은 화면이 뜬다. (기본 젠킨스 주소)

 

 

4.

위에 /Users부터 시작하는 경로에 위치한 initialAdminPassword 파일을 보면 패스워드가 있으니 그걸 입력하면 다음 페이지로 넘어 갈 수 있다. 터미널 켜서 vi 모드로 들어가서 읽었다!

 

 

 

5.

위와 같은 플러그인 설치 관련 화면이 뜨는데, 뭘 설치할지 모르겠으면 좌측(추천 플러그인 설치)을 클릭하자. 필요한 게 있으면 추후에 설치 가능하다.

 

 

6.

위와 같은 추천 플러그인들이 설치가 된다.

 

 

 

 

7.

admin으로 사용할 계정 정보 입력하기

 

 

 

 

8.

젠킨스 url을 설정해준다. 기본값은 localhost:8080이다.

테스트용이니까 로컬에서 8100 포트로 쓰기 위해 localhost:8100으로 설정햇다. 추후 ip를 써도 되고 dns 도메인 주소를 써도 된다!

 

주의) Mac os에서 brew로 설치한 경우 여기서 바꿔준다고해서 젠킨스의 url이 바뀌지 않는다.. (윈도우 서버의 경우 위처럼 하면 끝)

따로 설정파일 수정해줘야한다.

처음에는 초기화면에서 제공해준 경로에 있는 config 파일을 확인했는데 여기서 바꿔준 localhost:8100으로 바껴있는 걸 확인하고 헤맸다.

이후 brew install로 설치한 경우 brew 관련 경로로 들어가서 설정 파일을 추가로 수정해줘야 한다는 걸 알게됐다.

 

 

opt/homebrew/opt/jenkins-lts 경로에 들어가면 homebrew.mxcl.jenkins-lts.plist 파일이 존재한다.

 

 

vi 모드로 들어가서 httpPort 부분을 8100으로 고쳐줬다.(기존에는 8080으로 돼있었다.) 이후 ip 주소를 바꾸려면 바로 위의 어드레스 부분을 수정해야 한다.

 

10.

설치 및 기본 세팅 끝! 

이제 파이프라인을 설정해보자!

 

 

 

11.

젠킨스 아이템

젠킨스에서 CI/CD를 구축하기 위해서는 아이템을 생성해야 한다.

대표적인 방법으로는 프리스타일 프로젝트와 파이프라인 방식이 있다.

 

프리스타일 방식은 GUI 방식으로 쉽지만 커스터마이징이 어렵다는 단점이 있고,

파이프라인 방식은 스크립트를 직접 짜야 해서 번거롭지만 자유롭다는 장점이 있다.

 

파이프라인 방식으로 진행을 하겠다!

 

 

 

12. 아이템 세팅

  • CI/CD 대상 깃허브 url을 입력해주자! 테스트를 위해 private repository에 있는 프로젝트를 넣어줬다.
  • 오래된 빌드 이력이 계속 남으면 지저분하니까 5개 정도로 설정해줬다.
  • 깃허브 hook trigger 부분을 체크해주자!
    • GitHub 저장소에 연결된 웹훅을 사용하여 이벤트를 수신하고, 이벤트가 발생할 때마다 Jenkins 서버에 알려준다. 변경 감지!

== GitHub로 이동 == 

 

13. 깃허브 레포지토리 세팅에서 Webhooks → add webhook을 눌러주자

 

 

14.

Payload URL에 원하는 젠킨스 주소/github-webhook/을 입력

 

* 테스트 목적이라면 ngrok을 설치해서 이용하자

=> 외부에서 로컬 서버로 접속 가능하게 도와주는 터널 프로그램이다. 무료다.

위에처럼 내 로컬 서버의 주소를 외부에서 접근 가능한 주소로 변경해준다.

(물론 계속 할 수 있는 건 아니다! 세션 방식이라 시간제한이 있다) 

 

Content type은 application/json으로 하자 push event에 적용할 거라 저것만 체크했다.

 

 

 

 

15.

이번엔 레포지토리 세팅이 아니라 내 계정의 setting을 누르자! 그 후에 밑으로 쭉 누르면 Developer settings를 클릭

 

 

16.

Personal access tokens → tokens → generate new token 을 순서대로 눌러서

젠킨스에 등록해줄 토큰을 발급받자!

 

 

 

17.

토큰 권한이다. 이것 저것 항목이 많은데 다용도로 쓸 수 있게 원하는 항목들 체크해줘도 된다.

테스트용이라 만료기한도 무제한으로 하고 repo와 admin:repo_hook만 체크했다.

이제 맨 밑의 Generate Token 버튼을 클릭하면 토큰값을 알려준다.

 

 

 

18.

여기서 보여주는 토큰값은 지금 잘 복사해서 다른 곳에 잘 저장해놔야한다.

위에 경고 메시지에서 볼 수 있듯이 토큰 값을 다시 볼 수 있는 방법이 없기 때문이다.

 

 

 

== 다시 젠킨스 서버로 이동 ==

 

 

19.

젠킨스 관리에서 Credentials 클릭

 

 

20.

global 클릭

 

 

 

 

21.

add credentials 클릭

 

 

 

 

22.

Username with password 방식으로 깃허브 아이디와 아까 발급 받은 토큰 값을 넣어주자!!

 

 

 

 

 

== 젠킨스 툴 설정 ==

 

 

23.

툴 설정을 해주자!

JDK는 현재 로컬의 원하는 자바 경로를 명시해 주고, 그래들은 젠킨스에서 자동으로 인스톨하게 설정만 해주면 된다.

 

 

== 젠킨스 추가 플러그인설치 ==

 

 

 

24.

Docker Commons, Docker Pipeline 설치해주자!!!!

 

이제 스크립트만 작성해주면 CI/CD 파이프라인 구성을 끝낼 수 있다!!

 

참고)

== Mac os에서 젠킨스 서버 실행 시에 한정된 추가 주의 사항 ==

 

엄청 헤맸던 문제점

: Docker.. 인식...

 

파이프라인에서 스크립트를 작성해주는데 도커 관련 명령어가 하나도 안먹혔다.

 

https://stackoverflow.com/questions/40043004/docker-command-not-found-mac-mini-only-happens-in-jenkins-shell-step-but-wo/58688536#58688536

 

docker: command not found ( mac mini ) only happens in jenkins shell step but work from command prompt

I'm facing this weird problem , struggling to solve since almost couple of days. Working: On mac mini command prompt , I switch to jenkins user and can run docker command without any problem. Not

stackoverflow.com

 

결국 스택 오브 플로우에서 관련 레퍼런스를 찾아서 해결할 수 있었다.

 

Mac Os의 경우 

8번 과정의 젠킨스 url 수정때와 마찬가지로 brew 관련 설정파일에서 추가로 Docker 경로를 인식해줘야 한다. 

 

opt/homebrew/opt/jenkins-lts/homebrew.mxcl.jenkins-lts.plist

를 vi 모드로 수정해주자.. 이래서 도커에서 젠킨스를 띄워야하나 싶었다..!! mac os에서 하려니 불편..!!

 

 

빨간 박스 부분을 추가해주면 된다!

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>homebrew.mxcl.jenkins-lts</string>
        <key>LimitLoadToSessionType</key>
        <array>
                <string>Aqua</string>
                <string>Background</string>
                <string>LoginWindow</string>
                <string>StandardIO</string>
                <string>System</string>
        </array>
        <key>ProgramArguments</key>
        <array>
                <string>/opt/homebrew/opt/openjdk/bin/java</string>
                <string>-Dmail.smtp.starttls.enable=true</string>
                <string>-jar</string>
                <string>/opt/homebrew/opt/jenkins-lts/libexec/jenkins.war</string>
                <string>--httpListenAddress=127.0.0.1</string>
                <string>--httpPort=8100</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    <key>EnvironmentVariables</key>
    <dict>
      <key>PATH</key>
      <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Docker.app/Contents/Resources/bin/:/Users/Kh0a/Library/Group\ Containers/group.com.docker/Applications/Docker.app/Contents/Resources/bin</string>
    </dict>
"homebrew.mxcl.jenkins-lts.plist" 32L, 1107B

 

 

 

 

이제 진짜로 스크립트 작성만 남았다고 볼 수 있다..!

 

 

25.

파이프라인 스크립트를 입력해주자

  • 여기선 git clone 단계, 빌드 단계, 배포단계로 작성했다.
  • 원래는 도커 허브를 써서 도커 이미지를 푸시하고, 배포 서버에서 풀 받아서 배포하도록 명령하는 것이 더 적합하지만 그렇게까지는 하지 않았다. 도커 허브도 무료 사용 시 private repository 제한이 있다.
  •  현재 Mac-os CI/CD 테스트용으로 로컬에서 작성한 스크립트는 아래와 같다.

 

pipeline {
    agent any
    
    environment {
        DOCKER_IMAGE = 'assignment-image'
        CONTAINER_NAME = 'assignment'
    }

    tools {
        gradle 'gradle-8.0'
        jdk 'java-17'
    }
    
    stages {
        stage('Clone'){
            steps {
                git branch: 'main', credentialsId: '젠킨스 설정에서 만든 credential의 id입력', url: 'git Clone할 주소를 입력하자'
            }
        }
        
        stage('Build'){
            steps {
                echo "test"
                sh '''
                    echo 'start bootJar'
                    ./gradlew clean bootJar
                '''
            }
        }
        
        stage('Stop and Remove Container') {
            steps {
                script {
                    def containerStatus = sh(script: 'docker inspect -f {{.State.Running}} assignment', returnStatus: true)
                    if (containerStatus == 0) {
                        sh 'docker stop assignment'
                        sh 'docker rm -f assignment'
                        sh 'docker rmi assignment-image'
                        sh 'docker builder prune -a -f'
                    } else {
                        echo "Container does not exist."
                    }
                }
            }
        }
        
        stage('Build-image') { 
            steps { 
                script {
                    docker.build('assignment-image')
                }
            } 
        }
        
        stage('Run Docker Container') {
            steps {
                script {
docker.image('assignment-image').run('-d -p 8080:8080 --restart=always --name assignment -e SPRING_PROFILES_ACTIVE=local')
                }
            }
        }
    }
}

 

 

스테이지별로 살펴보자면

 

1. stage('Clone')

: Clone 스테이지에서 git clone 받을 branch와 CredentialsId(깃허브 아이디와 토큰을 설정한!) 그리고 git clone 받을 주소를 입력해준다.

 

이후 깃허브 웹훅을 통해 push 이벤트 발생 시, 해당 브랜치의 변경감지를 통해 CI/CD 작업이 수행된다.

 

만약 초기에는 staging 브랜치를 클론 받도록 스크립트를 짜고

이후 위의 Clone 스테이지에서 운영 브랜치를 클론 받게 수정한다고 해도

수정 후 첫번째 파이프라인은 staging 브랜치가 변경 됐을 때 작동한다.

그리고 이후에는 운영 브랜치가 변경되면 작동하게 될 것이다.

 

 

2. stage('Build')

: 빌드 작업을 통해 테스트 코드 등이 제대로 작성 됐는지 알 수 있다.

 

3.stage('Stop and Remove Container') 

: 기존 배포 중인 컨테이너가 있다면 종료 후 제거한다.

 

4.stage('Build-image') 

: 도커 이미지를 빌드한다.

 

5.stage('Run Docker Container') 

: 도커 컨테이너 실행하여 배포 작업을 진행한다.

 

 

단지 예시일 뿐, 위와 같은 방식으로 본인이 원하는 CI/CD 파이프라인을 구축하면 된다!! 

 

 

==최종 성공 화면==

 

 

1.

인텔리제이에서 해당 레포지토리의 특정 브랜치에 push 작업

 

 

 

2.

깃허브에서 해당 레포지토리의 세팅에서 Webhooks를 들어가서 해당 내역을 보면

위와 같이 젠킨스 서버에 성공적으로 요청이 보내졌음을 알 수 있다.

 

 

 

 

 

3.

이후 젠킨스 서버로 돌아가서 만들었던 아이템에 들어가고

밑에 Github Hook Log를 보면 아래와 같이 Webhooks 요청을 잘 받았음을 알 수있다.

 

 

 

 

4.

메인화면에서도 아래와 같이 해당 브랜치 커밋내역과 함께 파이프라인이 성공적으로 진행됐음을 알 수 있다.

commit 내역이 궁금하다면 클릭 시, 깃허브 해당 커밋 내역으로 이동이 된다.

 

 

 

 

 

'SPRING&JAVA' 카테고리의 다른 글

스프링 배치 - 2편(DB)  (0) 2024.03.25
스프링 배치 - 1편  (0) 2024.03.18
AOP, Custom Annotation 활용기  (0) 2023.11.07
View Table + JPA 매핑  (0) 2023.11.06
Schema 여정기 Multi-Tenancy(feat. PostgreSQL)  (0) 2023.11.01
Comments