Dazzling 개발 노트

[CI/CD] 4. Jenkins Pipeline Script를 작성해 배포하기 본문

DevOps/CICD

[CI/CD] 4. Jenkins Pipeline Script를 작성해 배포하기

dj._.dazzling 2023. 12. 22. 21:17

지난 게시글에서는 간단한 pipeline을 작성해 Jenkins와 GitHub를 연결해 보았다.

 

Jenkins - GitHub - Docker 연동을 위해 Jenkins Pipeline Script를 작성해보도록 하겠다.

이 Script를 통해 Jenkins에서 Docker(WAS)로 배포가 진행된다.

 

일단 지난 번에 설정한 Pipeline을

Jenkins 서버에서가 아닌 프로젝트 내 파일로 관리하도록 Jenkins 프로젝트의 설정을 변경한다.

 

Jenkins 사이트 > 프로젝트 > 구성 > Pipeline에서 다음과 같이 설정한다.

- Definition을 Pipeline script from SCM으로 변경한다.

- SCM을 Git으로 지정하고 Repository URL을 입력한다.

- Credentials에는 미리 등록해둔 credential 목록이 표출된다. github-access-token을 선택한다.

 

 

- Branch는 원하는 branch로 지정한다. 나는 main으로 설정했다.

- Script path는 프로젝트 내의 Jenkins 설정 파일명을 의미한다. 기본값인 Jenkinsfile을 유지했다.

 

저장버튼을 눌러 Jenkins 프로젝트의 설정 내용을 저장한다.

 

프로젝트에 Jenkinsfile 추가 및 설정

나는 프로젝트를 SpringBoot를 사용했다.

가장 최상위 경로에 Jenkinsfile을 생성한다.

 

내가 작성한 script이다.

나는 파이프라인으로 총 6개의 단계로 생성했다.

Checkout > Clone > Build Gradle > Build Docker Image > Push Image to Docker Hub > Run Docker Container

 

각각의 단계는 stage로 구분된다.

각 단계마다 시작과 끝을 알리기 위해 echo를 통해 문자열을 출력했다.

 

Jenkins에서 docker image를 만들고

Docker Hub에 image를 등록한다.

WAS 서버에 ssh를 통해 접속한 후에

Docker Hub로부터 image를 가져온다.

image를 바탕으로 container를 실행한다.

 

이 과정에 의해 Jenkins, WAS 서버 모두 Docker 설치가 필요하다.

SSH 접속을 위해 ssh 플러그인이 필요하다. 플러그인 설치와 관련된 내용은 지난 게시글을 참고한다.

중간에 Docker를 실행하면서 Dockerfile을 실행하게 된다.

Dockerfile의 내용도 아래 적어두었으니 참고하면 된다.

 

파이프라인의 script는 정해진 답이 있는 것은 아니고,

규칙에 맞춰서 원하는대로 작성하면 된다.

꼭 그대로 따라하기 보다는 script를 이해하고 직접 작성해보면 좋을 것 같다!

# Jenkinsfile
pipeline {
    agent any
    environment {
        //Server Info
        ip = "(WAS IP 주소)"
        username = "ubuntu"

        //Spring Info
        springname = "(원하는 것으로 지정)"
        port = "(원하는 것으로 지정)"

        //Docker Info
        imagename = "(원하는 것으로 지정)"
        dockerCredential = "docker-access-key"
        dockerImage = ''
        tagname = "dev"

        //GitHub Info
        giturl = 'https://github.com/(Repository URL)'
        gitCredential = "github-access-token"
        branchname = "main"
    }
    stages {
        stage('Git Repository Clone') {
            steps {
                echo 'Clone the Repository...'
                    git url: giturl,
                    branch: branchname,
                    credentialsId: gitCredential
            }
            post {
                success {
                    echo 'Successfully Cloned Repository'
                }
                failure {
                    error 'This pipeline stops here...'
                }
            }
        }
        stage('Build Gradle') {
            steps {
                echo 'Permission to gradlew...'
                script {
                    sh 'chmod +x ./gradlew'
                }
                echo 'building the application...'
                dir ('.'){
                    sh """
                    ./gradlew clean build --exclude-task test
                    """
                }
            }
            post {
                success {
                    echo 'Successfully Build Gradle'
                }
                failure {
                    error 'This pipeline stops here...'
                }
            }
        }
        stage('Build Docker Image'){
            steps {
                echo 'building docker image...'
                script {
                    imagename = "(사용자이름)/${imagename}"
                    dockerImage = docker.build imagename
                }
            }
            post {
                success {
                    echo 'Successfully Build Image'
                }
                failure {
                    error 'This pipeline stops here...'
                }
            }
        }
        stage('Push Image To Docker Hub'){
            steps {
                echo 'pushing docker image...'
                script {
                    docker.withRegistry( '', dockerCredential) {
                        dockerImage.push("dev")
                    }
                }
            }
            post {
                success {
                    echo 'Successfully Push Image'
                }
                failure {
                    error 'This pipeline stops here...'
                }
            }
        }
        stage('Run Docker Container on Dev Server'){
            steps {
                echo 'Run Container on Dev Server...'
                sshagent(['ec2-ssh']) {
                    sh 'ssh -o StrictHostKeyChecking=no ${username}@${ip} "whoami"'

                    sh "ssh -o StrictHostKeyChecking=no ${username}@${ip} 'docker ps -f name=${springname} -q | xargs --no-run-if-empty docker container stop'"
                    sh "ssh -o StrictHostKeyChecking=no ${username}@${ip} 'docker container ls -a -fname=${springname} -q | xargs --no-run-if-empty docker container rm'"
                    sh "ssh -o StrictHostKeyChecking=no ${username}@${ip} 'docker images -f reference=${imagename}:${tagname} -q | xargs --no-run-if-empty docker image rmi'"


                    sh "ssh -o StrictHostKeyChecking=no ${username}@${ip} 'docker pull ${imagename}:${tagname}'"
                    sh "ssh -o StrictHostKeyChecking=no ${username}@${ip} 'docker run -d -p 80:${port} -p ${port}:${port} --name ${springname} ${imagename}:${tagname}'"
                }
            }
            post {
                success {
                    slackSend (
                        channel: '#jenkins',
                        color: '#00FF00',
                        message: "SUCCESS: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
                    )
                }
                failure {
                    slackSend (
                        channel: '#jenkins',
                        color: '#FF0000',
                        message: "FAIL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})"
                    )
                }
            }
        }
    }
}

 

# Dockerfile
FROM openjdk:11-jdk AS builder
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
RUN chmod +x ./gradlew
RUN ./gradlew bootJar
FROM openjdk:11-slim
COPY --from=builder build/libs/*.jar (projectname 입력).jar
VOLUME /tmp
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=main", "(projectname 입력).jar"]

 

 

참고

https://junhyunny.github.io/information/jenkins/jenkins-deploy-ec2-using-docker/