[Infra] Spring Boot Pipeline 구축

[Infra] Spring Boot Pipeline 구축

Dockerfile

FROM openjdk:{버전}
LABEL authors="{작성자}"
COPY build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

 

 

  • backend 폴더 내에 추가

Pipeline

  • 멀티브런치를 이용해 분리했을 경우, Manged File > groovy file > pipeline jenkins 파일 생성해서 작성
pipeline {
    agent any
    tools {
        gradle "gradle"
    }
    options {
        disableConcurrentBuilds()
    }
  • tools: 파이프라인에서 사용할 도구를 정의, gradle 도구 사용
  • options: 파이프라인 옵션을 설정, disableConcurrentBuilds()를 호출하여 동시 빌드를 비활성화

Checkout

        stage('Checkout') {
            steps {
                git branch: env.GIT_BRANCH, credentialsId: '{git 사용자 계정 credentialId}', url: '{git url}'
                script {
                    def branchName = sh(script: "git rev-parse --abbrev-ref HEAD", returnStdout: true).trim()
                    if (branchName != 'develop') {
                        echo "This job only runs on the develop branch. Current branch is ${branchName}. Aborting the build."
                        currentBuild.result = 'ABORTED'
                        return
                    }
                }
            }
        }
  • git branch를 통해 서버로 pull을 받음

Application.yml

        stage('application.yml download') {
            steps {
                dir("./backend/PostitMS") {
                    withCredentials([file(credentialsId: 'application-yml', variable: 'applicationConfigFile')]) {
                        script {
                            if (!fileExists('src/main/resources')) {
                                sh 'mkdir src/main/resources'
                            }
                            sh 'cp $applicationConfigFile src/main/resources/application.yml'
                        }
                    }
                }
            }
        }

 

  • application.yml 과 같은 보안 파일들은 git에 올리면 안되므로, credential에 올리고 다운 받는 형태로 구현

Build

        stage('Build BackEnd') {
            steps {
                script {
                    def currentDir = sh(script: 'pwd', returnStdout: true).trim()
                    echo "The current directory is: ${currentDir}"
                    dir("./backend") {
                        sh 'bash gradlew build'
                    }
                    dir("./backend") {
                        sh 'docker rmi -f backend:latest'
                        sh 'docker build -t backend .'
                    }
                }
            }
        }
  • spring build 후 docker image로 build

Deploy

        stage('Deploy Backend') {
            steps {
                script {
                  sh "docker-compose -f docker-compose.yml down"
                  sh "docker-compose -f docker-compose.yml up -d --no-deps --build"
                }
            }
        }
  • docker-compose로 이전에 있던걸 내리고 현재 build 한 것을 올림

docker-compose.yml

version: '3'

services:
  backend:
    image: "{backend 이미지}"
    container_name: "backend"
    networks:
    - infra
    ports:
    - "8000:8000"

networks:
   infra:
      external: true

Health Check

stage('Health Check') {
            steps {
                script {
                    def maxRetries = 60
                    def retries = 0
                    def success = false

                    while (!success && retries < maxRetries) {
                        try {
                            def healthResponse = sh(script: "curl -s -o /dev/null -w '%{http_code}' -k {url}/actuator/health", returnStdout: true).trim()

                            if (healthResponse == '200') {
                                success = true
                                echo "Service is up and running"
                            } else {
                                throw new Exception("Service response code: ${healthResponse}")
                            }
                        } catch (Exception e) {
                            retries++
                            echo "Attempt ${retries}/${maxRetries}: Health check failed with exception - ${e.message}"

                            if (retries < maxRetries) {
                                echo "Retrying in 1 second..."
                                sleep(1)
                            }
                        }
                    }

                    if (!success) {
                        error("Health check failed after ${maxRetries} attempts")
                    }
                }
            }
        }
  • spring boot 의 actuator을 이용해 health check -> 60번의 시도 후에도 연결이 되지 않으면 fail

 

'Infra' 카테고리의 다른 글

[Infra] SonarQube Jenkins 연동  (0) 2024.05.27
[Infra] BackEnd Blue-Green 배포  (1) 2024.05.27
[Infra] React Pipeline 구축  (0) 2024.05.25
[Infra] Nginx 설정  (0) 2024.05.25
[Infra] Docker-Compose 를 통한 DB 구축  (0) 2024.05.25