Jenkins 배포 환경 : Amazon Linux, Java 17, Git, Docker, Gradle
main
branch에 merge가 되면 GitHub Webhook
을 통해 Jenkins
에게 알린다.Jenkins
는 다음과 같은 동작을 수행한다.Git clone
-> Gradle로 Spring Boot 프로젝트 Build
-> Docker Image화
-> GHCR (GitHub Container Registry)에 Push
-> WAS 서버에 원격 접속
-> GHCR로부터 Pull
-> Docker Container Run
먼저 원격으로 서버에 배포를 하기 위해서는 SSH
프로토콜로 접근해야 한다.
또한 GitHub
에서 Webhook
을 받기 위해서 플러그인이 필요하다.
해당 작업들을 도와주는 플러그인을 설치해보자.
처음에는 Publish over SSH
플러그인을 사용하려 했으나, 보안 문제로 인해 이제는 Jenkins에서 지원을 안 해준다고 한다.
Dashboard -> Jenkins 관리 -> Plugins -> Available plusgins
순으로 들어가 SSH Agent
, GitHub Integeration
과 Generic Webhook Trigger
를 검색하여 설치하자.
Dashboard -> {item name} -> Pipeline Syntax
로 이동한 다음 Sample Step
항목에서 sshagent: SSH Agent
를 선택하고 아래 +Add
버튼을 클릭하고 Jenkins
를 클릭한다.
Kind
: SSH Username with private key
선택Scope
: Global
로 선택ID
: 해당 Credential을 식별할 값Username
: 해당 서버에 접근할 계정명 (Amazon Linux는 ec2-user
/ 우분투는 ubuntu
가 디폴트)Private Key Enter directly
: 체크Key
: ssh Private Key(.pem) 추가연결하기 전에 인바운드 규칙에 22번(SSH) 포트에 접근을 Jenkins IP도 허용해야한다!!
Jenkins
에서 Gradle
로 Spring Boot
프로젝트를 Build
해서 배포
할 계획이다.
Dashboard -> Jenkins 관리 -> Tools -> Gradle installations -> Add Gradle
name
: 마음대로 설정Version
: Spring Boot 프로젝트와 버전을 맞춰준다!설정이 끝나면 Save
버튼을 눌러 저장하면 된다!
Dashboard -> Jenkins 관리 -> Credentials -> System -> Global credentials (unrestricted)
에서 + Add Credentials
버튼을 클릭한다.
Username
: GitHub 아이디
Password
: GitHub Access Token
ID
: 해당 자격증명을 식별할 용도로써 원하는 이름을 지정해주면 된다.다 작성했으면 Create
버튼 누르기
+ 새로운 Item
을 클릭해준다.
item 이름을 설정해주고 Pipeline
을 선택한 후 OK
를 클릭해준다.
item을 생성하면 해당 item의 Configuration로 넘어갈 것이다.
이제 Configuration을 설정해보자!
GitHub project
를 체크하고, 배포하려는 GitHub Repository URL을 적어준다.
우리는 GitHub Webhook
이용할 것이기 때문에
Build Triggers
에서 GitHub hook trigger for GITScm polling
을 체크해준다.
아래 Pipeline
부분으로 이동해준다.
나는 Spring Boot 프로젝트 내에 Pipeline Script를 작성할 것이다.
Definition
: Pipeline script from SCM
SCM
: Git
으로 설정Repository URL
: 배포하려는 GitHub Repository URL
Credentials
: 위에서 만든 Credential을 설정Branch Specifer
: 트리거 받을려는 브랜치Script Path
: .jenkinsfile 위치 (프로젝트의 루트에 위치할 경우 파일명.jenkinsfile로 설정)특정 브랜치에 대해서만 동작시키고 싶으면 여기를 확인해주세요!
프로젝트에서 Script Path
에 설정한 경로에 jenkinsfile을 작성하면 된다!
Jenkins에서 환경 변수를 사용하고 싶으면 Dashboard -> Jenkins 관리 -> System
로 이동한 다음 Global properties
에서 Environment variables
를 체크하여 환경 변수를 추가하면 된다.
pipeline {
agent any
environment {
VERSION = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
DOCKER_IMAGE = "${DOCKER_REGISTRY}/test:${VERSION}"
}
stages {
stage ('Git clone') {
steps {
git branch: 'main', credentialsId: 'github-access-token',
url: ${GITHUB_REPO}
}
}
stage ('Gradle Build') {
steps {
sh '''
chmod +x gradlew
./gradlew clean bootJar
'''
}
}
stage ('Docker Image Build') {
steps {
sh '''
docker rmi -f \$(docker images -q) || true
docker build -t test .
docker tag test ${DOCKER_IMAGE}
export CR_PAT=${GITHUB_TOKEN}
echo \$CR_PAT | docker login ghcr.io -u ${GITHUB_ID} --password-stdin
docker push ${DOCKER_IMAGE}
'''
}
}
stage ('Deploy') {
steps {
sshagent (credentials: ['위에서_만든_SSH_Credential_ID']) {
sh '''
ssh -o StrictHostKeyChecking=no ${API_SERVER_USER}@${API_SERVER_IP} "docker login ghcr.io -u ${GITHUB_ID} --password ${GITHUB_TOKEN}"
ssh -o StrictHostKeyChecking=no ${API_SERVER_USER}@${API_SERVER_IP} "docker pull ${DOCKER_IMAGE}"
ssh -o StrictHostKeyChecking=no ${API_SERVER_USER}@${API_SERVER_IP} "docker stop test || true"
ssh -o StrictHostKeyChecking=no ${API_SERVER_USER}@${API_SERVER_IP} "docker rm test || true"
ssh -o StrictHostKeyChecking=no ${API_SERVER_USER}@${API_SERVER_IP} "docker rm test || true"
ssh -o StrictHostKeyChecking=no ${API_SERVER_USER}@${API_SERVER_IP} "docker run -d --name test -p 8080:8080 ${DOCKER_IMAGE}"
'''
}
}
}
}
}
이제 GitHub Repository의 main 브랜치가 변경될 때마다 자동으로 배포가 될 수 있게 만들어보자!
GitHub 로그인 후 본인 계정 페이지에서
Settings -> Developer settings -> Personal access tokens -> Tokens (classic) -> Generate new token -> Generate new token (classic)
순서대로 들어가 토큰을 생성한다.
Note
: Token의 이름 (마음대로 짓기)repo
와 admin:repo_hook
은 꼭 체크하기!!생성된 토큰값은 해당 페이지를 나가면 다시 볼 수 없으므로 다른 곳에 저장해두길 바란다.
Webhook을 받을려는 GitHub Repository -> Settings -> Webhooks -> Add webhook
Payload URL
: http://{Jenkins 서버 IP}:{Jenkins Port}/github-webhook/
(/
빠지면 안됨!!)Content type
: application/json
Secret
: 발급 받은 GitHub Access Token
SSL verification
: Jenkins 서버가 HTTPS
가 적용되었다면 Enable
로 해주고 Payload URL
도 https
로 변경해주면 된다!Push Event
만 Trigger
로 받을 것이다!나는 테스트 용도로만 하는 것이기에 HTTPS
를 적용하지 않았다.
아마 별다른 보안 그룹을 설정하지 않았으면 ping
요청부터 실패
했을 것이다.
아래 링크를 통해 Jenkins 서버의 보안 그룹
을 수정하자!
GitHub Webhook 실패 시 참고!
Dashboard -> Jenkins 관리 -> System
Add GitHub Server
를 클린한 다음 GitHub Server
를 클릭하자.
+Add
를 클릭한 다음 Jenkins
를 클릭하면 아래와 같은 창이 나온다.
Kind
: Secret Text
로 설정Secret
: 위에서 발급 받은 GitHub Token
ID
: 해당 자격증명을 식별할 용도로써 원하는 이름을 지정다 작성했으면 Add
버튼을 눌러 추가하고, 이전 창의 Credentials
을 방금 만든 ID로 설정하고 저장하면 된다!
Spring Boot 서버로 접속하면 페이지가 뜨는 것을 확인할 수 있었다!
처음에는 Jenkins를 Docker Image로 받아서 사용했는데, Docker 컨테이너 내부에서 Docker 명령어를 사용할 수 없어서 로컬에 다시 설치해서 해결했다...
그 외에도 Linux 명령어를 잘 모르고, Pipeline도 처음 작성하다 보니까 수많은 에러를 많이 만난 것 같다.
확실히 설계까지의 과정이 오래 걸리긴 하지만, GitHub에 Push만 하면 자동으로 배포해줘서 진짜 편리하다.
Jenkins/Nginx로 무중단 배포 하기 1편 | HYK
[DevOps] Jenkins를 통한 CI/CD 구축기 2편 (Backend CI/CD 구축) | Seongwon.dev
[CI/CD] Jenkins와 GitHub 연동하기 | rungoat.log
Jenkins pipeline + Docker SpringBoot프로젝트 SSHAgent로 배포하기(+Slack Notification) | devdo
[AWS] EC2 Jenkins -(2) Github와 연동, 자동 빌드 적용하기 | yunSeok
docker image를 삭제하는 다양한 방법들 | soonbee