FireDrago
[배포] jenkins 사용하여 배포 자동화 하기 본문
jenkins 뭐하는 건데?

Jenkins를 사용하면 Github 리포지토리에서 코드를 다운로드하고,
자동으로 빌드하여 생성된 jar 파일을 서버에 전달하고 실행할 수 있다.
이 모든 작업이 버튼 한 번으로 가능해진다.
- Github 코드 다운로드
- Build: jar 파일 생성
- 백엔드 서버에 jar 전달
- jar 파일 실행
또한, Github webhook 설정을 추가하면 Github에 코드가 push될 때 이 작업을 자동으로 실행할 수도 있다.
webhook 설정에 대한 자세한 내용은 다음 포스트에서 알아보자
1. 리눅스 서버에 Docker 와 jenkins 설치하기
먼저 vultr 인스턴스를 하나 생성했다. os는 RockyLinux 9버전을 사용했다. jenkins를 사용하기 위한 서버다.
1. 리눅스 업데이트 :
시스템의 패키지 관리자(dnf)를 사용하여 설치된 모든 패키지를 최신 버전으로 업데이트하는 명령
시스템이 안정적이고 안전하게 동작하도록 보장하기 위해 실행한다.
sudo dnf update -y
2. 도커 설치: 도커를 설치하고 젠킨스 이미지를 설치하는 이유는 설치가 간편하고, 여러 서버에서 일관된 환경을 제공한다
sudo dnf install dnf-plugins-core -y
- DNF의 기능을 확장하여 추가적인 명령어나 옵션을 사용할 수 있게 해준다.
sudo dnf confing-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
- Docker 패키지를 설치할 때 Docker의 공식 저장소에서 최신 버전의 Docker를 다운로드할 수 있도록 한다.
sudo dnf install docker-ce docker-ce-cli containerd.io -y
- docker-ce (Community Edition): Docker의 오픈 소스 버전을 의미한다.
- docker-ce-cli: Docker 명령줄 인터페이스(CLI)
- containerd.io: 컨테이너 런타임 Docker의 핵심 컴포넌트 중 하나로, 컨테이너를 생성하고 관리한다.
3. 도커 서비스 시작 :
sudo systemctl start docker
- 도커를 실행한다.
sudo systemctl enable docker
- 시스템 부팅시 도커가 자동으로 시작되도록 한다.
4. jenkins 도커 이미지를 pull & 컨테이너 시작 : Docker 컨테이너에서 Jenkins를 실행
sudo docker run -d -p 8080:8080 -p 50000:50000 --name jenkins --restart=always
-v jenkins_home:/var/jenkins_home jenkins/jenkins:lts
- '-p 8080:8080' : 호스트의 포트 8080을 컨테이너의 포트 8080에 매핑, jenkins 웹 인터페이스 접속 포트
- '-p 50000:50000' : 호스트의 포트 50000을 컨테이너의 포트 50000에 매핑, Jenkins 에이전트와 통신 포트
- ' --name jenkins' : 생성되는 컨테이너의 이름을 jenkins로 지정, 컨테이너를 쉽게 식별하고 관리
- ' --restart=always ' : Docker 데몬이 시작될 때, 컨테이너가 중지되었을 때 자동으로 재시작하도록 설정
- ' -v jenkins_home:/var/jenkins_home ' : Jenkins의 데이터(설정, 빌드 로그, 플러그인 등)를 영구적으로 저장
- ' jenkins/jenkins:lts' : Jenkins의 LTS(Long Term Support) 버전 이미지를 사용, (안정적인 버전)
jenkins 환경설정
5. 서버ip주소:8080 => 젠킨스 접속
6. 젠킨스 초기 비밀번호를 확인하고 접속할때 입력해준다.
sudo docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
- 젠킨스 초기 비밀번호를 확인하고 접속할 때 입력해준다.
7. 'install suggested plugins' 눌러 플러그인 설치한다. 젠킨스 계정을 생성한다.
8. new item -> Pipeline 생성한다.

9. 파이프 라인 스크립트를 작성한다.
pipeline {
agent any
tools {
gradle 'Gradle'
}
environment {
JASYPT_PASSWORD = credentials('jasypt-password-id') // JASYPT 암호화 비밀번호를 환경 변수로 설정
SERVER_IP = '***.***.***.' // 배포할 서버의 IP 주소
DEPLOY_PATH = '/root' // 서버의 배포 경로
JAR_FILE = 'build/libs/bobzip-0.0.1-SNAPSHOT.jar' // 빌드된 JAR 파일 경로
LOG_FILE = 'app.log' // 애플리케이션 로그 파일 이름
RUN_APP_COMMAND = "nohup java -Dspring.profiles.active=prod -Djasypt.encryptor.password=${JASYPT_PASSWORD} -jar $DEPLOY_PATH/bobzip-0.0.1-SNAPSHOT.jar > $DEPLOY_PATH/$LOG_FILE 2>&1 &" // 애플리케이션 실행 명령
CHECK_LOG_COMMAND = "grep -q 'Started BobzipApplication in' $DEPLOY_PATH/$LOG_FILE" // 로그에서 애플리케이션 시작 확인 명령
STOP_APP_COMMAND = """
pgrep -f 'bobzip-0.0.1-SNAPSHOT.jar' && \
pkill -f 'bobzip-0.0.1-SNAPSHOT.jar' || \
echo "No process found"
""" // 애플리케이션 종료 명령
}
stages {
stage('Checkout') {
steps {
git url: 'https://github.com/Firedrago95/project_bobzip', branch: 'main' // Git 저장소에서 코드 체크아웃
}
}
stage('Prepare') {
steps {
script {
sh 'chmod +x ./gradlew' // gradlew 파일에 실행 권한 추가
}
}
}
stage('Build') {
steps {
script {
sh "./gradlew clean build -x test -Pjasypt.encryptor.password=${JASYPT_PASSWORD}" // Gradle을 사용하여 빌드 수행, 테스트 제외
}
}
}
stage('Deploy') {
steps {
script {
sshagent(['deploy_ssh_key']) {
// 기존 애플리케이션 종료
sh script: "ssh root@$SERVER_IP '${STOP_APP_COMMAND}'", returnStatus: true
// JAR 파일을 원격 서버로 복사
sh "scp -o StrictHostKeyChecking=no $JAR_FILE root@$SERVER_IP:$DEPLOY_PATH/"
// 원격 서버에서 애플리케이션을 백그라운드에서 실행
sh """
ssh -o StrictHostKeyChecking=no root@$SERVER_IP '
echo "Starting new application..."
$RUN_APP_COMMAND
'
"""
// 애플리케이션이 시작될 시간을 주기 위해 30초 대기
sleep 30
// 로그 파일에서 애플리케이션 시작 메시지를 확인
def result = sh(script: "ssh -o StrictHostKeyChecking=no root@$SERVER_IP '$CHECK_LOG_COMMAND'", returnStatus: true)
if (result == 0) {
echo 'Deployment was successful.' // 배포 성공 메시지 출력
} else {
error 'Deployment failed.' // 배포 실패 메시지 출력
}
}
}
}
}
}
post {
success {
echo 'Pipeline completed successfully.' // 파이프라인 성공 메시지 출력
}
failure {
echo 'Pipeline failed' // 파이프라인 실패 메시지 출력
}
}
}

10. 파이프라인 스크립트에서 Gradle 사용하기 위해 젠킨스 관리페이지 > Tools > Gradle installations name 'Gradle'
11. 개인키 공개키 설정
docker ps -q
- 컨테이너 id 확인
docker exec -it [컨테이너id] /bin/bash
- bash 설정 파일로 들어온다.
ssh-keygen -t rsa -b 4096
- 개인키 / 공개키 쌍 생성
cat /var/jenkins_home/.ssh/id_rsa.pub
- 공개키 복사
---------------------------------- 애플리케이션 설치된 서버로 이동 ----------------------------
vi ~/.ssh/authorized_keys
- 입력 'i'로 편집모드 진입 => 복사한 공개키 붙여넣기
서버의 방화벽 설정, 자바버전 설치
---------------------------------- jenkins 웹 인터페이스 --------------------------------------------
jenkins 관리 > 플러그인 > ssh agent 플러그인 설치
jenkins 관리 > credentials > add credentials > SSHUsername with private key
id = 'deploy_ssh_key', username = jenkins
private key는 "cat /var/jenkins_home/.ssh/id_rsa" 실행 붙여넣기 (----start-----, -----END---- 포함)
< jenkins 배포된 이후, 계속 실행중인 경우>
- 애플리케이션 설치된 서버에서 'ps -aux | grep java' : 'java' 이름을 가진 실행중인 프로세스를 검색
- kill -15 [프로세스 id] : 애플리케이션을 종료
- 파이프라인 수정 : 'nohub' 사용으로 특정 로그 있으면 성공, 실패 출력하도록 변경
nohup java -Dspring.profiles.active=prod -Djasypt.encryptor.password=${JASYPT_PASSWORD} -jar $DEPLOY_PATH/bobzip-0.0.1-SNAPSHOT.jar

'지금 빌드' 누르면 빌드가 잘 실행되는것을 볼 수 있다.
'프로그래밍 > 배포' 카테고리의 다른 글
| [GithubActions] GithubActions로 Docker CD 구성하기 (0) | 2025.07.29 |
|---|---|
| [GithubActions] GithubActions로 Docker CI 구성하기 (0) | 2025.07.27 |
| [vultr] DB를 사용하는 프로젝트 배포하기 (0) | 2024.07.23 |
| pscp명령어로 원격서버 <-> 로컬 파일전송하기 (0) | 2024.07.22 |
| [배포] Vultr 이용하여 간단한 프로젝트 배포해보기 (0) | 2024.07.18 |
