도커와 젠킨스로 스프링부트+그래들 프로젝트 배포(3/4) - 젠킨스와 깃허브 연동 및 배포
이 게시글은 도커와 젠킨스로 스프링부트+그래들 프로젝트 배포의 세번째 글입니다
이번엔 젠킨스에서 깃허브 레파지토리를 연동해보고 자신의 프로젝트를 배포 해보겠습니다.
최종적으로는 젠킨스 컨테이너에서 DooD(Docker-Outside-Of-Docker)방식으로
스프링부트+그래들 프로젝트의 깃허브 레파지토리에 webhook을 설정해서
push가 발생하면 자동으로 젠킨스에서 빌드 후 배포까지 하는것이 목표입니다.
젠킨스에서 깃허브 연동하기
제가 실습하는 환경입니다
서버 - AWS Lightsail
인스턴스 플랜 - $10 플랜 (메모리 : 2GB, 프로세스 : 1vCPU)
OS - Ubuntu 20.04 LTS (20년4월에 나온 Long Term Support할 예정인 버전)
터미널 클라이언트 - mobaXterm (putty같은 소프트웨어. 본인이 편한걸 사용하시면 됩니다. 큰 의미 없습니다)
패키지 관리자 - apt (콘솔or터미널에서 패키시 설치할때 사용하는 패키지 관리 도구)
도커 - Docker Community Edition 23.0.1
※참고 : 젠킨스를 사용하면서 메모리 사용량을 조회해 보니 컨테이너 실행만으로 600MB의 메모리를 사용하고 빌드 시 1GB 가까이 메모리를 사용합니다. 저는 아주 간단한 프로젝트를 빌드 했지만 프로젝트의 규모가 커질수록 메모리 사용량은 늘어날 것으로 보입니다. 이 점 서버 구성할 때 참고하세요! (AWS에서 프리 티어 플랜을 사용할 경우 작동이 원활하지 않을 수 있습니다.)
[더 좋은 방법이 있거나 의문, 수정사항 언제든 댓글 달아주세요.]
부가적인 설명에 대해서는 접은글로 적어두겠습니다 필요에따라 [더보기]를 눌러 확인해보세요.
1. 젠킨스에서 사용할 깃허브 토큰 발급
1-1 깃허브 사용자 이미지를 누른후 Settings클릭
1-2 왼쪽 제일 하단의 Developer settings를 클릭
1-3 순서대로 클릭해서 Generate new token(classic) 클릭
1-4 원하는 토큰 명 입력 후 기한 선택 (저는 No expiration을 선택 하겠습니다.)
1-5 [repo] 권한과 [admin:repo_hook] 권한 두가지만 체크 후 Generate token 클릭
repo권한은 리포지토리의 정보와 커밋 내역을 읽고 쓰는 등의 권한 입니다.
admin:repo_hook 권한은 네 번째 게시글에서 레파지토리에 푸시가 발생하면 자동으로 젠킨스가 그것을 감지할 수 있게끔 해주기 위한 권한입니다.
1-6 생성된 토큰의 토큰값 확인
※참고 : 이 화면에서 보이는 토큰 값(빨간 박스)이 처음이자 마지막으로 토큰 값을 볼 수 있는 화면입니다. 꼭 다른 곳에 메모해두시고 외부에 공개하시면 안 됩니다. 만약 토큰 값을 잊어버리셨으면 기존 토큰은 삭제 후 재생성 하시면 됩니다.
2. 젠킨스에서 깃허브 설정
2-1 대시보드에서 Jenkins 관리 - 시스템 설정 클릭
젠킨스의 버전 혹은 브라우저의 설정에 따라 용어가 한글 또는 영어로 보일수있습니다.
[시스템 설정]은 영어로 보일경우 System으로 표시됩니다.
2-2 스크롤을 내리면 있는 GitHub 영역에서 AddGitHub Server - GitHub Server 를 눌러줍니다
2-3 새롭게 나타는 영역에서 원하는 이름을 입력하고 Add - Jenkins를 눌러줍니다
2-4 Credentials를 입력해줍니다
2-5 Credentials 드롭박스를 누르면 입력한 Credentials가 보입니다. 선택후 Test connection 진행
3. Pipeline 생성
3-1 메뉴에서 새로운 Item을 클릭합니다.
3-2 아이템명을 입력 후 Pipeline을 선택한 뒤 OK를 클릭합니다.
4. Pipeline 설정
4.1 Do not allow the pipeline to resume if the controller restarts(파이프라인 충돌 방지 옵션) 체크
Do not allow the pipeline to resume if the controller restarts 항목 외에는 체크하는 항목 없습니다.
다음 단계에서 필요한 항목은 다음 게시글에서 설명하겠습니다
지금은 Do not allow the pipeline to resume if the controller restarts항목만 체크해주세요
4-2 Pipeline script 작성
※참고 : 이 부분은 Spring boot + Gradle 프로젝트 기준입니다. 이 예시를 기준으로 이해하시고 나서 자신의 프로젝트 환경에 맞게끔 적절하게 변형하시면 됩니다.
예시에서 사용한 프로젝트의 Pipeline script입니다.
pipeline {
agent any
stages {
stage('Checkout') {
steps {
git branch: '원하는 브랜치명', url: '본인의 깃 레파지토리 URL(.git으로 끝나는링크)'
}
}
stage('Build') {
steps {
sh './gradlew build'
}
}
stage('Dockerize') {
steps {
sh '''
docker stop my_container_name || true
docker rm my_container_name || true
docker rmi my_image_name || true
docker build -t my_image_name .
'''
}
}
stage('Deploy') {
steps {
sh 'docker run -d --name my_container_name -p 8080:8080 my_image_name'
}
}
}
}
하지만 각각의 my_container_name과 my_image_name이 들어있는 위치는 맞춰주셔야 됩니다.
4-3 Pipeline 빌드시 실행 순서
위와같이 스크립트를 작성하고 빌드를 할 경우 실행 순서에 대해서 알려드리겠습니다!
Pipeline 빌드버튼 클릭 → Pipeline script시작 → stage('Checkout')에 정의된 깃 레파지토리의 브랜치 소스를 가져옵니다
→ stage('build') 에서 sh명령어 './gradlew build' 에 의해 해당 레파지토리 소스를 그래들로 빌드를 실행합니다. ('./gradlew' 는 현재 경로에서의 gradlew파일을 의미합니다. Checkout단계에서 깃 레파지토리 소스를 가져왔기때문에 './' 경로는 레파지토리의 최상단을 의미합니다)
→ stage('Dockerize') 에선 sh 명령어로
① docker stop my_container_name || true
② docker rm my_container_name || true
③ docker rmi my_image_name || true
④ docker build -t my_image_name . ←마지막에 .(점)이 있으니 꼭 적어주세요.
네가지를 실행합니다.
①은 이름이 my_container_name인 컨테이너가 실행중이라면 해당 컨테이너를 중지시킵니다. 중지시킬 컨테이너가 없다면 "|| true" 에 의해서 다음 명령어로 진행됩니다.
②는 중지시킨 컨테이너를 삭제합니다.
③은 이름이 my_image_name인 이미지 파일을 삭제합니다.
(여기까지 진행이 되면 기존에 존재하던 프로젝트 정보는 모두 삭제돼서 없어집니다. 그렇기 때문에 빌드를 여러번 실행하더라도 데이터가 계속 쌓이지 않습니다.)
④는 이제 새롭게 my_image_name의 이름으로 이미지를 빌드합니다. 이미지파일은 Dockerfile을 기준으로 빌드되는데, 마지막에 . 을 찍었기때문에 도커는 현재 디렉토리에서 Dockerfile을 찾습니다. (위에서 말했듯이 현재 디렉토리는 깃 레파지토리의 최상위 경로입니다.)
#Dockerfile 내용
FROM openjdk:11-jre-slim
COPY build/libs/everything-shop-0.0.1-SNAPSHOT.jar app.jar
CMD ["java", "-jar", "app.jar"]
FROM openjdk:11-jre-slim : Java 11 실행 환경이 설치된 리눅스 기반 이미지를 만든다는 의미입니다.
COPY build/libs/YOUR_PROJECT-0.0.1-SNAPSHOT.jar app.jar : build/libs/YOUR_PROJECT-0.0.1-SNAPSHOT.jar 파일을 이미지에 app.jar로 포함시킵니다. 저희는 stage('build') 단계에서 빌드를 진행했기때문에 그래들 빌드를 진행하면 자동으로 build/libs 경로에 본인의 프로젝트 명이 들어간 YOUR_PROJECT-0.0.1-SNAPSHOT.jar 파일이 생성됩니다. 그래서 그 파일을 이미지에 app.jar란 이름으로 포함시키는 것입니다.
CMD ["java", "-jar", "app.jar"] : CMD명령어는 컨테이너가 실행됐을때 실행되는 기본 명령어를 지정합니다. ["java", "-jar", "app.jar"]는 app.jar파일을 실행시키는 명령어입니다.
따라서 ④ 명령어는 위의 도커파일 내용을 기반으로 이미지파일을 생성합니다 (-t my_image_name 옵션에 의해 이미지 이름은 my_image_name이 됩니다.)
→ stage('Deploy')에선 이전 단계에서 생성된 이미지 파일을 기반으로 컨테이너를 실행시킵니다. sh명령어를 살펴보면
docker run -d --name my_container_name -p 8080:8080 my_image_name
-d : 컨테이너를 백그라운드에서 실행시키는 옵션
--name my_container_name : 컨테이너의 이름을 my_container_name으로 지정하는 옵션
-p 8080:8080: 호스트포트(8080)와 컨테이너포트(8080)를 연결하는 옵션
my_image_name : 컨테이너로 실행시킬 이미지 파일을 적어줍니다
→ Pipeline빌드 완료
위의 순서대로 Pipeline 빌드가 이뤄지고 배포 또한 완료됩니다.
조금 생소할수도 있으나 처음부터 천천히 읽어보시면 그리 어렵지않으실겁니다!
4-3 빌드 실행
5. 서버 포트 개방
배포는 완료했지만 아직 aws에서 8080포트를 개방하지않았기때문에 해당 포트를 열어줘야됩니다.
Lightsail 인스턴스의 네트워킹탭에서 포트를 추가합니다.
6. 배포된 프로젝트 확인