CI/CD 구축하기 - (2)

danhyeon·2024년 9월 15일

Deploy

목록 보기
3/6

CI/CD 구축하는 프로세스는 다음과 같다.
Github Push - WebHook trigger - Jenkinsfile - Git Repo Pull - Project Build - Docker Image - Run Docker Container

+) 젠킨스에 privatge repo를 연결하는 경우 아래 참고
링크텍스트

+) 특정 브랜치에만 trigger 받기

[jenkins]
Generic Webhook Trigger Jenkins Plugin install
PipeLine-Configuration 내
github project check
Generic Webhook Trigger check
Post content Param Expression = $.ref
JSONPath check
Token 임의의 값으로 입력
Optional filter Expression = refs/heads/main
Text = $branch
GitHub hook trigger ~ polling check

[webhook]
Payload URL = [jenkins URL]/generic-webhook-trigger/invoke?token=[위 임의 설정한 토큰]
Content type = application/json
Just the push event check

젠킨스 설치

docker run \
  --name jenkins_1 \
  -p 8081:8080 \
  -e TZ=Asia/Seoul \
  -v /docker_projects/jenkins_1/var/jenkins_home:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /docker_projects/jenkins_1/data:/data \
  -u root \
  -d \
  --restart unless-stopped \
  jenkins/jenkins:jdk17

젠킨스 컨테이너 내 도커 설치 - 도커 명령을 사용하기 위함

apt-get update -y
apt-get install -y ca-certificates curl gnupg lsb-release
mkdir -p /etc/apt/keyrings
rm /etc/apt/keyrings/docker.gpg
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli docker-compose-plugin
exit

스프링부트 Jenkinsfile(default)

pipeline {
    agent any

    environment {
        timestamp = "${System.currentTimeMillis() / 1000L}"
    }

    stages {
        stage('Prepare') {
            steps {
                script {
                    // Get the ID of the sbb:latest image
                    def oldImageId = sh(script: "docker images shop-boot-demo:latest -q", returnStdout: true).trim()
                    env.oldImageId = oldImageId
                }

                git branch: 'main',
                	// private repo인 경우
                    // credentialsId: 'id';
                    // id는 jenkins - setting - credentials에 username with password로 github에서 발급된 token secret 등록
                    url: 'https://github.com/sodanhyun/shop-boot-demo'
            }

            post {
                success {
                    sh 'echo "Successfully Cloned Repository"'
                }
                failure {
                    sh 'echo "Fail Cloned Repository"'
                }
            }
        }

        stage('Build Gradle') {
            steps {
                dir('.') {
                    sh """
                    chmod +x gradlew
                    """
                }

                dir('.') {
                    sh """
                    ./gradlew clean bootjar
                    """
                }
            }

            post {
                success {
                    sh 'echo "Successfully Build Gradle Test"'
                }
                 failure {
                    sh 'echo "Fail Build Gradle Test"'
                }
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    sh "docker build -t shop-boot-demo:${timestamp} ."
                }
            }
        }

        stage('Run Docker Container') {
            steps {
                script {
                    // Check if the container is already running
                    def isRunning = sh(script: "docker ps -q -f name=shop-boot-demo", returnStdout: true).trim()

                    if (isRunning) {
                        sh "docker rm -f shop-boot-demo"
                    }

                    // Run the new container
                    try {
                        sh """
                        docker run \
                          --name=shop-boot-demo \
                          -p 8080:8080 \
                          -v /docker_projects/shop-boot-demo/volumes/gen:/gen \
                          --restart unless-stopped \
                          -e TZ=Asia/Seoul \
                          -d \
                          shop-boot-demo:${timestamp}
                        """
                    } catch (Exception e) {
                        // If the container failed to run, remove it and the image
                        isRunning = sh(script: "docker ps -q -f name=shop-boot-demo", returnStdout: true).trim()

                        if (isRunning) {
                            sh "docker rm -f shop-boot-demo"
                        }

                        def imageExists = sh(script: "docker images -q shop-boot-demo:${timestamp}", returnStdout: true).trim()

                        if (imageExists) {
                            sh "docker rmi shop-boot-demo:${timestamp}"
                        }

                        error("Failed to run the Docker container.")
                    }

                    // If there's an existing 'latest' image, remove it
                    def latestExists = sh(script: "docker images -q shop-boot-demo:latest", returnStdout: true).trim()

                    if (latestExists) {
                        sh "docker rmi shop-boot-demo:latest"

                        if(!oldImageId.isEmpty()) {
                        	sh "docker rmi ${oldImageId}"
                        }
                    }

                    // Tag the new image as 'latest'
                    sh "docker tag shop-boot-demo:${env.timestamp} shop-boot-demo:latest"
                }
            }
        }
    }
}

리액트

pipeline {  
    agent any

    environment {
            timestamp = "${System.currentTimeMillis() / 1000L}"
        }

    stages {

        stage('Prepare') {
            steps {
                script {
                    // Get the ID of the sbb:latest image
                    def oldImageId = sh(script: "docker images fe_wqproject:latest -q", returnStdout: true).trim()
                    env.oldImageId = oldImageId
                }

                git branch: 'main',
                    url: 'https://github.com/sodanhyun/wqproject-fe'
            }

            post {
                success {
                    sh 'echo "Successfully Cloned Repository"'
                }
                failure {
                    sh 'echo "Fail Cloned Repository"'
                }
            }
        }

        stage('Build') {  
            steps {
                dir('.') {
                    sh """
                    npm install
                    """
                }

                dir('.') {
                    sh """
                    CI=false npm run build
                    """
                }
            }
            post {
                success {
                    sh 'echo "Successfully Build Test"'
                }
                 failure {
                    sh 'echo "Fail Build Test"'
                }
            }
        }  
        stage('Docker Build') {  
            steps {  
                sh 'docker build -t fe_wqproject:${timestamp} .'
            }  
        }

        stage('Run Docker Container') {
            steps {
                script {
                    // Check if the container is already running
                    def isRunning = sh(script: "docker ps -q -f name=fe_wqproject", returnStdout: true).trim()

                    if (isRunning) {
                        sh "docker rm -f fe_wqproject"
                    }

                    // Run the new container
                    try {
                        sh """
                        docker run \
                          --name=fe_wqproject \
                          -p 82:80 \
                          -v /docker_projects/wqproejct-fe/volumes/gen:/gen \
                          --restart unless-stopped \
                          --network application \
                          -e TZ=Asia/Seoul \
                          -d \
                          fe_wqproject:${timestamp}
                        """
                    } catch (Exception e) {
                        // If the container failed to run, remove it and the image
                        isRunning = sh(script: "docker ps -q -f name=fe_wqproject", returnStdout: true).trim()

                        if (isRunning) {
                            sh "docker rm -f fe_wqproject"
                        }

                        def imageExists = sh(script: "docker images -q fe_wqproject:${timestamp}", returnStdout: true).trim()

                        if (imageExists) {
                            sh "docker rmi fe_wqproject:${timestamp}"
                        }

                        error("Failed to run the Docker container.")
                    }

                    // If there's an existing 'latest' image, remove it
                    def latestExists = sh(script: "docker images -q fe_wqproject:latest", returnStdout: true).trim()

                    if (latestExists) {
                        sh "docker rmi fe_wqproject:latest"

                        if(!oldImageId.isEmpty()) {
                            sh "docker rmi ${oldImageId}"
                        }
                    }

                    // Tag the new image as 'latest'
                    sh "docker tag fe_wqproject:${env.timestamp} fe_wqproject:latest"
                }
            }
        }
    }  
}
profile
문제를 반복하지 않기

0개의 댓글