젠킨스 파이프라인(리액트)

문철환·2024년 4월 2일
post-thumbnail
pipeline {
    agent any
    tools {nodejs "nodejs"}
    
    environment {
        imageName = "이미지이름 넣기"
        registryCredential = 'dockerhub' //젠킨스에 등록해놓은 자격증명서
        dockerImage = ''
        
        releaseServerAccount = 'ubuntu'
        releaseServerUri = '서비스 URL EC2서버'
        releasePort = '리액트가 사용하는 포트'
    }

    stages {
        stage('Git Clone') {
            steps {
                git branch: 'FE',
                    credentialsId: 'gitlab', //젠킨스에 등록해놓은 자격증명서
                    url: 'URL.git'  //git clone할 때 사용하는 url
            }
        }
        stage('Image Build & DockerHub Push') {
            steps {
                dir('frontend') {
                    script {
                        docker.withRegistry('', registryCredential) {
                            sh "docker buildx create --use --name mybuilder"
                            sh "docker buildx build --platform linux/amd64,linux/arm64 -t $imageName:latest --push ."
                        }
                    }
                }
            }
        }
        stage('Before Service Stop') {
            steps {
                sshagent(credentials: ['ubuntu-c106']) {
                    sh '''
                    if test "`ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker ps -aq --filter ancestor=mooncheolhwan/frontend:latest"`"; then
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker stop $(docker ps -aq --filter ancestor=mooncheolhwan/frontend:latest)"
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker rm -f $(docker ps -aq --filter ancestor=mooncheolhwan/frontend:latest)"
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker rmi mooncheolhwan/frontend:latest"
                    fi
                    '''
                }
            }
        }
        stage('DockerHub Pull') {
            steps {
                sshagent(credentials: ['ubuntu-c106']) {
                    sh "ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri 'sudo docker pull $imageName:latest'"
                }
            }
        }
        stage('Service Start') {
            steps {
                sshagent(credentials: ['ubuntu-c106']) {
                    sh '''
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "sudo docker rm -f fe"
                    ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "sudo docker run -i -e TZ=Asia/Seoul --name fe -p $releasePort:$releasePort -d $imageName:latest"
                    '''
                }
            }
        }
        stage('Service Check') {
            steps {
                sshagent(credentials: ['ubuntu-c106']) {
                    sh '''
                        #!/bin/bash
                        
                        for retry_count in \$(seq 20)
                        do
                          if curl -s "URL" > /dev/null
                          then
                              curl -d '{"text":"Release Complete"}' -H "Content-Type: application/json" -X POST 메타모스트 웹훅
                              break
                          fi
                        
                          if [ $retry_count -eq 20 ]
                          then
                            curl -d '{"text":"Release Fail"}' -H "Content-Type: application/json" -X POST 메타모스트 웹훅
                            exit 1
                          fi
                        
                          echo "The server is not alive yet. Retry health check in 5 seconds..."
                          sleep 5
                        done
                    '''
                }
            }
        }
       
    }
}

위 코드로 진행되었습니다.
단계는 6단계로,
1. Git Clone : Git 저장소에서 소스 코드를 가져옵니다.
2. Image Build & DockerHub Push : Docker 이미지를 빌드하고 DockerHub에 푸시합니다.
3. Before Service Stop : 이전에 실행된 Docker 컨테이너를 중지하고 제거합니다.
4. DockerHub Pull : 새로 업데이트된 Docker이미지를 서버로 가져옵니다.
5. Service Start : 새로운 Docker컨테이너를 시작합니다.
6. Service Check : 서비스가 올바르게 시작되었는지 확인합니다.


agent any : 어떤 에이전트에서든 실행될 수 있다.
tools : 파이프라인에서 사용하는 도구
environment : 환경 변수 정의함.
stages : 파이프라인의 주요 단계 정의
steps : 각 단계에서 실행할 명령, shell 스크립트로 실행됨.


  • docker buildx create --use --name mybuilder
    • Docker Buildx 빌더를 생성하고 사용할 이름을 지정하는 명령
    • --use : 새로 생성된 빌더를 사용하도록 설정합니다.
    • --name mybuilder : 새로 생성된 빌더의 이름을 "mybuilder"로 지정합니다.
    • mybuilder 빌더를 사용하여 다중 아키텍처 이미지를 빌드할 수 있게 됩니다.
  • docker buildx build --platform linux/amd64,linux/arm64 -t $imageName:latest --push .
    • Docker Buildx를 사용하여 다중 아키텍처 이미지를 빌드하고 푸시하는 명령
    • --platform linux/amd64,linux/arm64 : 빌드할 이미지의 플랫폼을 지정합니다. 여기서는 Linux의 amd64 아키텍처와 arm64 아키텍처를 지정했습니다. 즉, 이 명령은 amd64와 arm64 아키텍처용 이미지를 동시에 빌드합니다.
    • -t $imageName:latest : 빌드한 이미지에 태그를 지정합니다. $imageName은 환경 변수로 설정된 이미지 이름을 나타냅니다. latest는 태그로서, 이 이미지가 최신 버전임을 나타냅니다.
    • --push : 빌드된 이미지를 레지스트리에 푸시합니다.
    • . : 현재 디렉토리에서 Dockerfile을 사용하여 이미지를 빌드합니다.

  • if test "`ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker ps -aq --filter ancestor=mooncheolhwan/frontend:latest"`"; then
    • 원격 서버에서 실행 중인 모든 컨테이너의 ID를 가져와서 filter 옵션을 사용하여 특정 이미지를 뽑아냅니다.
    • 필터된 ID가 mooncheolhwan/frontend:latest이면 아래코득가 실행됩니다.
  • "ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker stop $(docker ps -aq --filter ancestor=mooncheolhwan/frontend:latest)"
    • docker stop 명령을 사용하여 원격 서버에서 실행 중인 특정 이미지를 기반으로한 컨테이너를 중지합니다.
  • "ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker rm -f $(docker ps -aq --filter ancestor=mooncheolhwan/frontend:latest)"
    • docker rm -f 명령을 사용하여 원격 서버에서 실행 중인 특정 이미지를 기반으로한 컨테이너를 강제로 제거합니다.
  • "ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "docker rmi mooncheolhwan/frontend:latest"
    • docker rmi 명령을 사용하여 해당 이미지를 원격 서버에서 제거합니다.

  • ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "sudo docker rm -f fe"
    • 원격 서버에 SSH를 통해 접속한 후, sudo docker rm -f fe 명령을 실행합니다.
      - 이 명령은 fe라는 이름의 Docker 컨테이너를 강제로 제거합니다.
    • -f 옵션은 강제로 컨테이너를 제거
  • ssh -o StrictHostKeyChecking=no $releaseServerAccount@$releaseServerUri "sudo docker run -i -e TZ=Asia/Seoul --name fe -p $releasePort:$releasePort -d $imageName:latest"
    • 원격 서버에 SSH를 통해 접속한 후, 새로운 Docker 컨테이너를 실행합니다.
    • -i : 인터랙티브 모드로 실행합니다.
    • -e TZ=Asia/Seoul : 컨테이너 내부의 시간대를 Asia/Seoul로 설정합니다.
    • --name fe : 컨테이너의 이름을 fe로 지정합니다.
    • -p $releasePort:$releasePort : 호스트의 $releasePort 포트를 컨테이너의 동일한 포트로 매핑합니다.
    • -d : 백그라운드 모드로 실행합니다.
    • $imageName:latest: 실행할 이미지의 이름과 태그를 지정합니다.
    • $imageName은 환경 변수로 설정된 이미지 이름을 나타냅니다.

마지막 step인 Service Check 코드에 대해 설명하자면,

  • for retry_count in \$(seq 20): 20번의 반복을 수행하는 for 루프를 시작합니다.
  • if curl -s "URL" > /dev/null: curl을 사용하여 특정 URL로 HTTP GET 요청을 보냅니다. -s 옵션은 silent 모드로 출력을 표시하지 않습니다. 응답은 /dev/null로 보냅니다.
  • curl -d '{"text":"Release Complete"}' -H "Content-Type: application/json" -X POST 메타모스트 웹훅: Release Complete 메시지를 포함한 JSON 데이터를 지정된 웹훅 URL로 POST 요청을 보냅니다.
  • break: 반복문을 종료합니다.
  • if [ $retry_count -eq 20 ]: 20번의 시도가 모두 실패한 경우 실행합니다.
  • curl -d '{"text":"Release Fail"}' -H "Content-Type: application/json" -X POST 메타모스트 웹훅 : Release Fail 메시지를 포함한 JSON 데이터를 지정된 웹훅 URL로 POST 요청을 보냅니다.
  • exit 1: 스크립트를 종료하고 오류 코드 1을 반환합니다.
  • echo "The server is not alive yet. Retry health check in 5 seconds...": 서버가 아직 준비되지 않았음을 나타내는 메시지를 출력합니다.
profile
밝고 빛나게

0개의 댓글