dayne의 블로그

젠킨스 자동 배포 파이프라인 스크립트 작성 예시 본문

CI CD/Jenkins

젠킨스 자동 배포 파이프라인 스크립트 작성 예시

dayne_ 2024. 10. 29. 15:28

목차

1. 예시 코드

2. 코드 설명

 

 


1. 예시 코드

pipeline {
    agent any
    environment {
        VERSION = "v0.1"
        SERV_IP = "***.***.***.***"
        SERV_PORT = "***"
        SERV_PASSWORD = "******"
    }
    stages {
        stage('Git Clone') {
            steps {
                slackSend (
                    channel: "#serv-pipeline-alarm",
                    color: "#99CC00",
                    message: "ServerOne 배포 시작: Serv-One-Frontend"
                )
                git branch: 'servOneDeploy', credentialsId: '******', url: 'http://******.git'
            }
        }
        stage('Build New Version ServOne') {
            steps {
                try {
                    dir('home/testprogram/src/fe/test_v1') {
                        sh "bash do_build.sh ${env.VERSION}_servone"
                    }
                }catch (Exception e) {
                    echo 'Docker Build Failed'
                    slackSend (
                        channel: "#serv-pipeline-alram",
                        color: "#FF3333",
                        message: "ServOne 빌드 실패: Serv-One-Frontend"
                    )
                }
            }
        }
        stage('Transmission ServOne Build File') {
            steps {
                sh "docker save -o /home/testprogram/src/servone_container/fe/servone_front_${env.VERSION}.tar servone_front:${env.VERSION}_servone"
                sh "sshpass -p ${env.SERV_PASSWORD} scp -o StrictHostKeyChecking=no -P ${env.SERV_PORT} /home/testprogram/src/servone_container/fe/servone_front_${env.VERSION}.tar root@${env.SERV_IP}:/home/testprogram/fe_containers"
            }    
        }
        stage('Stop Docker Container & Build new version Container') {
            steps {
                script {
                    try{
                        sh "sshpass -p ${env.SERV_PASSWORD} ssh -p ${env.SERV_PORT} root@${env.SERV_IP} 'docker stop servone_front && docker rm servone_front'"
                    }catch(Exception e){
                        echo 'Not Running Previous Container'
                    }
                }
                sh "sshpass -p ${env.SERV_PASSWORD} ssh -p ${env.SERV_PORT} root@${env.SERV_IP} 'docker load -i /home/testprogram/fe_containers/servone_front_${env.VERSION}.tar'"
            }
        }
        stage('Start New Version Container'){
            steps {
                script {
                    try {
                        sh "sshpass -p ${env.SERV_PASSWORD} ssh -p ${env.SERV_PORT} root@${env.SERV_IP} 'docker run -dit -p 1212:1212 --name servone_front -v /home/testprogram/tefiles:/home/testprogram servone_front:${env.VERSION}_servone'"
                    } catch (Exception e) {
                        slackSend(
                            channel: "#serv-pipeline-alram",
                            color: "#FF3333",
                            message: "빌드 실패: Serv-One-Frontend"
                        )
                    }
                }
                slackSend (
                    channel: "#serv-pipeline-alram",
                    color: "#99CC00",
                    message: "배포 성공: Serv-One-Frontend"
                )
            }
        }
    }
}

 

 


2. 코드 설명

전체적인 프로세스는, '테스트 서버'에서, 'testprogram' 프로그램에 대한 코드를 깃허브 레포지토리로부터 클론 받고 도커 이미지를 빌드한 후, 도커 이미지 파일로 만들어 '원격 서버'로 전송합니다.

이후, 기존에 실행 중이던 도커 컨테이너를 중지 및 삭제하고 새로운 도커 이미지를 사용해 도커 컨테이너를 생성 및 실행시키는 과정으로 진행됩니다.

 

// Git SCM 사용 (소스코드의 레포지토리에 dockerfile 포함시키고 빌드할 때마다 배포되는 방식)

 

기본적인 파이프라인 작성 방식은 아래 링크의 포스트에 설명되어 있습니다.

https://dayne-w.tistory.com/19

 

agent any
environment {
    VERSION = "v0.1"
    SERV_IP = "***.***.***.***"
    SERV_PORT = "***"
    SERV_PASSWORD = "******"
}

 

먼저 agent의 값으로 any를 설정하였습니다.

사용 가능한 어떤 agent에서도 파이프라인의 내용이 실행 가능하도록 합니다.

 

다음으로 스크립트 작성 시에 사용할 환경변수를 설정하였습니다.

  • VERSION : 현재 구현한 프로그램의 버전을 설정
  • SERV_IP : 새로 빌드한 도커 이미지를 배포하고자 하는 서버의 IP 주소 설정
  • SERV_PORT : 새로 빌드한 도커 이미지를 배포하고자 하는 서버의 PORT 번호 설정
  • SERV_PASSWORD : 배포하고자 하는 서버의 root 계정에 대한 비밀번호를 설정

 

stage('Git Clone') {
    steps {
        slackSend (
            channel: "#serv-pipeline-alarm",
            color: "#99CC00",
            message: "ServerOne 배포 시작: Serv-One-Frontend"
        )
        git branch: 'servOneDeploy', credentialsId: '******', url: 'http://******.git'
    }
}

 

 

'새롭게 도커 이미지를 생성하여 배포하고자 하는' 소스코드가 포함된 Git의 레포지토리를 설정해 주고, Push 또는 Merge로 인해 변경된 소스코드를 클론하는 작업을 진행합니다.

 

  • Slack 알림 전송
    • 먼저 slackSend 메서드를 호출하여 Slack의 #serv-pipeline-alarm 채널에 알림을 전송합니다. 알림 메시지는 "ServerOne 배포 시작: Serv-One-Frontend"이며, 메시지의 색상을 #99CC00으로 설정합니다. 이를 통해 파이프라인 시작 시점에 슬랙 채널에 배포 알림을 보내줍니다.
  • Git Clone
    • 그 다음 git 메서드를 호출하여 특정 Git 레포지토리에서 servOneDeploy 브랜치를 클론합니다. 클론 과정에서 credentialsId에 지정된 인증 정보를 사용하여 해당 Git 레포지토리에(http://******.git)에 접근합니다.

 

stage('Build New Version ServOne') {
    steps {
        try {
            dir('home/testprogram/src/fe/test_v1') {
                sh "bash do_build.sh ${env.VERSION}_servone"
            }
        }catch (Exception e) {
            echo 'Docker Build Failed'
            slackSend (
                channel: "#serv-pipeline-alram",
                color: "#FF3333",
                message: "ServOne 빌드 실패: Serv-One-Frontend"
            )
        }
    }
}

 

클론 받은 소스코드로 'ServOne' 서버에 배포할 도커 이미지를 빌드합니다.

 

  • 도커 이미지 빌드
    • dir 명령어를 사용해, 도커 이미지로 빌드하는 로직이 구현된 do_build.sh 파일의 위치로 이동합니다.
    • bash 명령어를 사용해서, do_build.sh 스크립트를 실행하는데, 이때 '${env.VERSION}_servone' 을 인자로 넘겨줍니다.
    • 결과로는 'servone_front:${env.VERSION}_servone' 이라는 도커 이미지가 빌드됩니다.
  • Slack 알림 전송
    • 이미지 파일 빌드 실패 시, 슬랙의 '#serv-pipeline-alarm' 채널에 지정해둔 message를 통해 빌드 실패 알림을 전송합니다.
※ do_build.sh
파일 내에, 'docker build -t servone_front:$1' 코드를 작성합니다.
-t 옵션을 통해 도커 이미지에 태그를 지정해 줍니다. 태그는 이미지의 이름과 버전을 설정하여 쉽게 관리할 수 있도록 해줍니다.
$1 은 스크립트 실행 시에 받는 첫 번째 인자를 의미하므로, 빌드 성공 시 servone_front:${env.VERSION}_servone 이라는 이름을 가진 도커 이미지가 빌드되는 것입니다.

 

stage('Transmission ServOne Build File') {
    steps {
        sh "docker save -o /home/testprogram/src/servone_container/fe/servone_front_${env.VERSION}.tar servone_front:${env.VERSION}_servone"
        sh "sshpass -p ${env.SERV_PASSWORD} scp -o StrictHostKeyChecking=no -P ${env.SERV_PORT} /home/testprogram/src/servone_container/fe/servone_front_${env.VERSION}.tar root@${env.SERV_IP}:/home/testprogram/fe_containers"
    }    
}

 

도커 이미지를 .tar 형태의 파일로 만든 후, 도커 이미지를 배포하고자 하는 서버로 해당 파일을 복사합니다.

  • 도커 이미지를 파일로 저장
    • docker save -o 명령어를 사용해서, 도커 이미지를 하나의 tar 아카이브 파일로 저장합니다.
    • -o 옵션은 저장할 파일의 경로와 이름을 지정하는 옵션입니다. 위의 예제에서는 servone_front:${env.VERSION}_servone 도커 이미지를 servone_front_${env.VERSION}.tar 파일로 저장합니다.
  • 도커 이미지 파일(tar 파일)을 원격 서버로 복사
    • sh
      • 쉘 스크립트 내에서 실행할 명령어를 나타냅니다. 위의 예제에서는 sshpass와 scp 명령을 실행합니다.
    • sshpass -p ${env.SERV_PASSWORD}
      • sshpass 를 사용하여, SSH 연결에 필요한 비밀번호를 자동으로 입력하는 부분입니다.
      • p ${env.SERV_PASSWORD} 는 환경 변수 SERV_PASSWORD에 저장된 비밀번호를 사용해 자동 로그인합니다.
    • scp
      • scp는 Secure Copy Protocol로, 파일을 로컬과 원격 서버 사이에 안전하게 복사하는 명령어입니다.
      • 여기서는 로컬 파일(테스트 서버의 도커 이미지 파일(tar))을 원격 서버(ServOne 서버)로 복사합니다.
    • StrictHostKeyChecking=no
      • SSH 연결 시에, 서버의 호스트 키를 검사하지 않도록 설정하는 옵션입니다.
      • 보통 SSH 접속 시, 서버의 호스트 키가 '처음 접속할 때의 로컬'에 저장되는데, 이를 무시하고 호스트 키를 확인하지 않겠다는 의미입니다.
      • 보안 측면에서 잠재적 위험이 있지만, 자동화된 스크립트에서 주로 사용합니다.
    • -P ${env.SERV_PORT}
      • SSH의 포트 번호를 지정하는 옵션입니다.
      • 기본적으로 SSH는 포트 22를 사용하지만, 다른 포트로 설정된 경우 해당 옵션을 통해 설정된 포트로 접속할 수 있습니다.
    • /home/testprogram/src/servone_container/fe/servone_front_${env.VERSION}.tar
      • 새로운 도커 이미지를 빌드하고, 도커 이미지 파일을 만든 테스트 서버(로컬 시스템)에서, 전송할 파일의 경로입니다.
    • root@${env.SERV_IP}:/home/testprogram/fe_containers
      • scp 명령의 대상 경로입니다.
      • 원격 서버의 IP 주소에 root 계정으로 접속한 후, 원격 서버의 /home/testprogram/fe_container 경로에 전송된 파일이 복사됩니다.

 

 

stage('Stop Docker Container & Build new version Container') {
    steps {
        script {
            try{
                sh "sshpass -p ${env.SERV_PASSWORD} ssh -p ${env.SERV_PORT} root@${env.SERV_IP} 'docker stop servone_front && docker rm servone_front'"
            }catch(Exception e){
                echo 'Not Running Previous Container'
            }
        }
        sh "sshpass -p ${env.SERV_PASSWORD} ssh -p ${env.SERV_PORT} root@${env.SERV_IP} 'docker load -i /home/testprogram/fe_containers/servone_front_${env.VERSION}.tar'"
    }
}

 

'원격 서버'에서 기존에 동작 중이던 도커 컨테이너를 중지시키고 삭제한 후, 복사된 도커 이미지 파일에서 도커 이미지를 로드합니다.

  • 기존에 실행 중이던 도커 컨테이너 중단 및 삭제
    • 'docker stop 기존 도커 컨테이너 이름' 과 'docker rm 기존 도커 컨테이너 이름' 명령어를 사용해서, 기존에 실행 중이던 도커 컨테이너의 실행을 중단하고 해당 컨테이너를 삭제합니다.
  • 이전에 복사된 도커 이미지 파일(tar)로부터, 도커 이미지 로드
    • docker load -i 명령어를 사용하여, scp를 통해 복사된 도커 이미지 파일 (servone_front_${env.VERSION}.tar)에서 도커 이미지(servone_front:${env.VERSION}_servone)를 로드합니다.

 

stage('Start New Version Container'){
    steps {
        script {
            try {
                sh "sshpass -p ${env.SERV_PASSWORD} ssh -p ${env.SERV_PORT} root@${env.SERV_IP} 'docker run -dit -p 1212:1212 --name servone_front -v /home/testprogram/tefiles:/home/testprogram servone_front:${env.VERSION}_servone'"
            } catch (Exception e) {
                slackSend(
                    channel: "#serv-pipeline-alram",
                    color: "#FF3333",
                    message: "빌드 실패: Serv-One-Frontend"
                )
            }
        }
        slackSend (
            channel: "#serv-pipeline-alram",
            color: "#99CC00",
            message: "배포 성공: Serv-One-Frontend"
        )
    }
}

 

도커 이미지 파일로부터 로드한 도커 이미지를 통해 도커 컨테이너를 생성하고 실행시킵니다.

  • 도커 컨테이너 생성 및 실행
    • docker run
      • Docker 컨테이너를 생성하고 실행하는 명령어입니다.
      • 여기서 컨테이너는 로드된 도커 이미지 (servone_front:${env.VERSION}_servone) 를 기반으로 생성됩니다.
    • -dit
      • d 옵션 : detach 모드로 실행하라는 의미입니다. 즉, 백그라운드에서 컨테이너를 실행합니다. 이렇게 하면 터미널이 컨테이너에 붙어 있지 않고, 컨테이너는 백그라운드에서 계속 동작합니다.
      • i : interactive 모드로, 표준 입력을 계속 유지합니다. 즉, 컨테이너가 실행되는 동안 입력을 받을 수 있도록 설정합니다.
      • t : pseudo-TTY(가상 터미널)를 할당합니다. 터미널을 에뮬레이션하여 사용자가 명령어를 실행할 수 있게 하는 가상 터미널을 제공합니다.
        • 에뮬레이션 : 한 시스템이 다른 시스템을 흉내 내어 그 시스템처럼 동작하도록 하는 기술
      • 이렇게 3가지 옵션을 함께 사용함으로써, 백그라운드에서 실행되지만 인터랙티브한 쉘을 사용할 수 있는 컨테이너를 실행합니다.
    • -p 1212:1212
      • 포트 포워딩 설정입니다. 호스트와 컨테이너 간의 포트를 매핑합니다.
      • 호스트의 1212번 포트를 컨테이너의 1212번 포트에 연결하라는 의미입니다. 따라서 호스트의 1212번 포트로 들어오는 요청은 컨테이너의 1212번 포트로 전달됩니다.
    • -name servone_front
      • 컨테이너의 이름을 지정하는 옵션입니다.
    • -v /home/testprogram/tefiles:/home/testprogram
      • v옵션은 볼륨 마운트 설정 옵션으로, 호스트(테스트 서버)와 컨테이너 간의 디렉토리를 공유할 수 있도록 마운트를 설정합니다.
      • /home/testprogram/tefiles 는 호스트의 디렉토리입니다.
      • /home/testprogram은 컨테이너 내부에서 해당 디렉토리가 마운트될 위치입니다.
      • 즉, 호스트의 /home/testprogram/tefiles 디렉토리가 컨테이너 내부의 /home/testprogram 디렉토리와 연결되어, 두 디렉토리 간의 파일을 공유할 수 있게 됩니다.
    • servone_front:${env.VERSION}_servone
      • 해당 도커 이미지를 통해서 새로운 도커 컨테이너가 생성되고, 실행됩니다.
  • Slack 알림 전송
    • 배포 성공 시, 슬랙의 '#serv-pipeline-alarm' 채널에 지정해둔 message를 통해 배포 성공 알림을 전송합니다.

 

 

 

'CI CD > Jenkins' 카테고리의 다른 글

Jenkins Pipeline 개념 및 문법 정리  (1) 2024.10.29
Jenkins 설명 및 설치 과정  (0) 2024.10.24