Jenkins, Docker를 통한 CI 환경 구축과 Slack 알람 받기

kindof

·

2022. 9. 21. 20:19

1. 소개

Jenkins는 CI 환경을 구축하는 데 있어 대표적인 사용하는 툴로써 정말 많은 서비스, 그리고 저희 회사에서도 사용하는 소프트웨어입니다.

 

사실 Jenkins 이외의 CI 툴도 많지만, Jenkins는 자바 기반으로 Window, Mac, Linux 등의 대부분 OS에서 동작한다는 점, 웹 인터페이스에서의 Configuration이 가능하고 많은 Plugin들을 지원해줌으로써 확장성이 좋은 장점 등이 있기 때문에 많은 서비스들에서 이용하고 있는 것 같습니다.

 

이번 포스팅에서는 직접 Docker를 사용해 프로젝트를 진행하는 가상 환경을 만드는 것부터, 그 안에 Jenkins CI 환경 구축하고 Slack에 해당 환경의 동작을 알림으로 받을 수 있는 기능까지 붙여보는 과정을 해보면서 Jenkins의 기능과 CI 환경의 동작에 대한 이해해보고자 합니다.

 

 

docker를 이용한 CI 구축 연습하기 (젠킨스, 슬랙)

안녕하세요? 이번 시간엔 도커로 CI 구축 연습하기 (젠킨스, slack) 예제를 진행해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을

jojoldu.tistory.com

이 프로젝트를 따라해보는 데 많은 참고를 했던 이동욱님의 블로그입니다. 많은 과정이 비슷하지만 5년 전에 작성한 글이기 때문에 다른 부분도 있어서 그런 부분까지 다시 짚어보면서 진행해보겠습니다.

 

2. Springboot 프로젝트 생성 및 Github 연결

먼저 아주 간단한 스프링부트 프로젝트를 하나 생성합니다.

start.spring.io

그리고 아래와 같이 build.gradle에 태스크를 하나 정의합니다.

plugins {
	id 'org.springframework.boot' version '2.7.3'
	id 'io.spring.dependency-management' version '1.0.13.RELEASE'
	id 'java'
}

group = 'com'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

task print() {
	doLast {
		println("Github push completed")
	}
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

해당 Task는 아래와 같이 gradle 명령어로 수행 가능합니다.

Task 동작

 

이제 이 쪼그만 프로젝트를 Github Repository에 올리겠습니다. Repo 생성 - Remote 저장소 연결 - Add - Commit - Push에 대한 자세한 과정은 생략하겠습니다.

Repository Push 완료

Jenkins는 여기서부터 Github 저장소에 변화가 생길 때마다 자동으로 빌드를 해 줄 예정입니다!

 

 

3. Docker를 통한 Jenkins 설치 및 실행

저는 M1에서 개발 중이고, 아래 링크를 따라하시면 도커를 설치하실 수 있습니다.

 

M1에 Docker 설치하는 방법 · snowdeer's Code Holic

M1에 Docker 설치하는 방법 23 Dec 2021 | MAC OS M1에 Docker 설치하는 방법 Docker 다운로드 Docker가 M1에서 동작할 수 있도록 정식 버전이 릴리즈되어 있습니다. 여기에서 다운로드할 수 있습니다. Docker Subsc

snowdeer.github.io


도커 설치가 완료됐다고 가정하고, CLI를 통해 Jenkins 컨테이너를 설치하고 구동시키겠습니다.

Docker + Jenkins

정상적으로 컨테이너가 올라가있으니, localhost:8085로 접속해보겠습니다.

Jenkins Start

 

그러면 위와 같이 Administrator Password를 입력하라는 창이 뜨는데요. 당황하지 마시고 아래와 같이 도커 log 파일을 열어서 확인해보시면 됩니다.

Jenkins administration password 찾기

위 사진에서는 /var~ 경로를 확인해보라고 나와있는데, 로컬 Shell에서 아무리 저 경로를 들어가도 나오지 않습니다! 현재 Jenkins는 Docker 위에서 동작하기 때문에 로컬 파일 시스템에서는 찾을 수 없는 것이죠. 그래서 Jenkins 컨테이너 안으로 들어가서(docker exec -it [Container ID] bash) 해당 경로를 찾으셔도 좋고, 제가 한 방법처럼 Docker log를 찾아보셔도 패스워드를 확인하실 수 있습니다.

어쨌든 해당 패스워드를 입력하신 후에 플러그인 설치(Suggested) + 계정 생성까지 해주시면 아래와 같이 Jenkins 접속 화면을 만날 수 있습니다.

Jenkins!

 

 

4. Jenkins 컨테이너 설정

이제 Jenkins에서 관리할 새로운 Item을 생성하겠습니다. [새로운 Item] 메뉴를 선택하시고 Item Name은 아무거나! [Freestyle project]를 선택하고 OK합니다. 그러면 아래와 같이 대시보드에 생성한 아이템이 보입니다.

아이템 생성 완료

 

이제 저기 보이는 jenkins-docker-slack 이라는 녀석이 Github를 감시하고, 변화가 생기면 특정 작업을 아이템 내에서 하도록 만들 것입니다. 그러기 위해서는 어떤 Github를 감시하고 어떤 작업을 할 지 저 녀석에게 알려줘야겠죠?

Configuration

위와 같이 해당 아이템의 [소스 코드 관리]에 들어가셔서 Git Repository URL을 넣어줍니다.

 

해당 URL은 자신의 Github repo에 가서 복사하시면 됩니다.

 

그리고 그 아래 [Credentials] 버튼을 클릭해서 아래처럼 자신의 github ID, password를 넣어줍니다. 당연한 말이지만, Github 저장소를 Jenkins가 관리하려면 Jenkions 쪽에게 아이디랑 비밀번호를 알려줘야 합니다.

Credential

 

위 과정을 다 하시면 아래와 같이 내용이 채워져 있어야 합니다.

 

그리고 맨 아래 [Branches to build]에는 기본적으로 */master가 들어가있는데, 저는 현재 Git의 정책에 따라 master대신 main을 사용하고 있기에 해당 부분을 */main으로 바꿨습니다. 자신이 push하는 브랜치를 적어주시면 됩니다.

Github 정보 입력 끝


다음으로는 해당 Github 레포지토리에 변화가 생기면 무슨 일을 할 지를 정해보겠습니다.

빌드 유발
Build Steps

위와 같이 [빌드 유발] 항목에 대해서는 Github hook trigger for GITScm polling을 선택해주시고 [Build Steps]에는 무슨 일을 할 것인지에 대한 내용으로 Execute shell 을 설정하겠습니다.

그리고 이전에 작성한 Task를 호출하는 ShellScript를 작성하여 빌드 수행이 정상적으로 되는지 확인하려고 합니다.

Execute Shell


자, 여기까지 진행됐다면 우리가 만든 Jenkins 컨테이너는 Github 레포지토리의 변화를 기다리고 있으며 Push가 일어나면 Trigger가 작동하여 빌드 후 Shell이 동작하도록 만들어졌습니다.

이제 반대편(Github)에 가서 설정을 마저 해주도록 하겠습니다.

 

5. Github Webhook, ngrok 설정

Github Webhook은 Github 내 어떤 이벤트 발생 시 POST Payload를 Webhook에 설정된 URL로 보내주는 역할을 합니다. 따라서 우리는 Webhook에 Jenkins URL을 입력하고, 저장소에 Push 이벤트가 발생하면 Jenkins에서 설정한 빌드를 트리거하도록 할 것입니다.

Github Webhook

위 사진과 같이 [Settings] - [Webhooks] 탭에 들어가서 Payload URL을 입력합니다. 단, 여기서 기존에 접속했던 Jenkins 서버(localhost:8085)를 입력하시면 안 되는데요. 아래 Stackoverflow에서 그 이유를 찾으실 수 있는데, 로컬 호스트에서 동작하는 Jenkins 서버의 경우 방화벽이나 NAT의 영향을 받기 때문에 Webhook이 전달되지 못한다는 것입니다.

https://stackoverflow.com/questions/33766275/i-need-help-setting-up-a-github-webhook-with-a-localhost-jenkins

 

그래서 이러한 문제를 해결하기 위해 ngrok을 사용할 것입니다. ngrok은 임의의 IP를 생성하여 localhost에서 동작하는 서버가 받는 요청을 Redirect해서 받는 일종의 프록시 서버입니다. 사용하기 편하고 무료이기 때문에 다른 웹 서버를 굳이 구축할 필요없이 사용할 수 있죠.

먼저 아래와 같은 커맨드로 ngork을 설치합니다.

$ brew install ngrok

그리고 8085 포트에 있는 로컬 호스트 서버를 ngrok을 통해 열어줍니다.

$ ngrok http 8085

그러면 아래와 같이 ngrok을 통해 열린 서버의 정보를 받을 수 있습니다.

ngrok

저기 [Forwarding]에 써져있는 주소가 우리가 사용할 Payload URL의 주소입니다. 다만, 저 주소 뒤에 '/github-webhook/'이라는 주소를 반드시 더 붙여주셔야 합니다. 그래야 Jenkins 설치 시 다운받은 플러그인이 해당 주소를 사용할 수 있게 됩니다.

 

6. Jenkins 동작 테스트

이제 위에서 ngrok을 통해 열어둔 서버를 통해 Jenkins를 실행시킨 뒤(위에서 실행한 ngrok을 켜 둔 상태로 하셔야 합니다), 이전에 만들어 둔 Item(jenkins-docker-slack)으로 들어가 빌드를 진행해보겠습니다.

Jenkins 동작 테스트

ngrok을 통해 사용하는 Jenkins 서버에서도 빌드가 성공적으로 진행됨을 알 수 있습니다.

이제 반대쪽(Github)에서 아래와 같이 프로젝트를 조금 수정한 뒤, 깃허브 저장소에 푸시해보겠습니다. 그러면 Jenkins에서 해당 이벤트에 대한 Payload를 받아서 예전에 설정한 것처럼 빌드가 유발되고, Shellscript가 실행되어야 합니다!

Github push
Jenkins Build

결과를 확인해보면 깃허브 Push 이벤트에 대해 Jenkins가 변화를 감지하고 빌드를 자동화하고 있음을 확인할 수 있습니다. 이렇게 함으로써 Github webhook을 통해 Jenkins와 연동은 완료되었습니다.

 

7. Slack 연동하기

마지막으로 진행할 내용은 Jenkins에서 자동 빌드가 일어나거나 실패할 때 해당 알림을 Slack으로 받아보는 것인데요. 많은 서비스나 회사에서 협업을 통해 Slack을 사용하기 때문에 이러한 빌드/배포 프로세스에 대한 알림 자동화는 꽤 유용할 수 있습니다.

먼저 Slack 아이디가 없으신 분은 하나를 만들고, 아무 채널이나 만들어주세요.

Slack 개설


그리고 아래와 같은 URL(https://[slack-project-name].slack.com/apps)에 접속하여 Jenkins 앱을 다운받습니다.

Slack에서 Jenkins 설치


Jenkins 설치를 진행하다보면 아래와 같은 화면이 나올텐데요. 해당 화면에서 팀 하위 도메인과 통합 토큰 자격 증명 ID를 잘 저장해주세요.

Domain, Integration code


그리고 이제 다시 Jenkins로 돌아와서 아래와 같이 Slack 플러그인을 설치합니다.


그리고 이제 위에서 저장해 둔 토큰 자격 증명 ID를 Credential에 추가합니다. 여기서 [Kind]는 Secret Text로 해주세요.

Integration code 작성


여기까지 진행하셨다면 이제 Jenkins 쪽 설정을 하나 더 해주시면 끝입니다. 바로 빌드 후에 Slack에 알림을 보내겠다는 설정인데요.

Jenkins 빌드 후 조치 추가

우리가 만들어 둔 아이템에 들어가 [Build Steps] - 빌드 후 조치 추가에 Slack Notifications를 추가해줍니다. 그리고 몇 가지 속성이 있을텐데 Start, Aborted, Failure, Success 등 항목 중 원하는 항목을 선택해주시면 됩니다.

이제 Jenkins는 깃허브의 이벤트 트리거를 받는 순간 빌드를 진행하고, Shellscript 수행, Slack에 알림을 보내는 행위를 하게 됩니다.

마지막으로 테스트를 진행해보겠습니다.

Github Push
Jenkins 빌드 자동화
Slack 알림

성공적으로 동작하는 것을 확인할 수 있습니다.

 

꽤 긴 호흡이 필요한 과제였지만, 직접 해보면서 안 되는 부분들을 해결해보고 이해하다 보니 많은 도움이 됐던 것 같습니다. 감사합니다.