Skip to content
ulimy edited this page Oct 26, 2022 · 7 revisions

기술 선택을 위한 고민 과정

Docker의 장단점

  • 장점👍
    • 쉽고 빠르게 환경을 구축할 수 있다.
    • 서로 다른 OS 에서도 같은 환경을 구축할 수 있다.
    • Container가 격리되어 있어서 독립된 환경을 보장한다.
    • Docker hub을 통해 image를 쉽게 pull, push 할 수 있다.
  • 단점👎
    • 초기 학습 비용이 든다.
    • Linux에서만 실행 가능하여 다른 환경에서는 VM 위에서 동작한다.

Github Actions의 장단점

  • 장점👍
    • repository와 CI/CD 툴을 함께 관리해서 쉽다.
    • public repository는 무료다.
  • 단점👎
    • EC2의 보안 관련 설정이 제한되어 있는 경우 사용하기 어렵다.
      • EC2에 접근할 권한이 있는 IAM이 필요하다. 그리고 우리에겐 새로운 IAM을 발급할 권한이 없다.
    • 최신 기술이므로 안정성에 의문이 있으며 레퍼런스가 부족하다.
    • private repository는 유료다 😭.

Jenkins의 장단점

  • 장점👍
    • 오랜 기간 사용되어 안정성이 검증되었고 레퍼런스가 풍부하다.
    • 실무에서 많이 사용한다.
    • 설정할 수 있는 범위가 넓다.
    • 오픈소스 기반이라 무료다.
  • 단점👎
    • 기본 환경 설정이 매우 복잡하다.
    • 별도의 빌드용 서버가 필요하다.
    • 학습 비용이 크다.

최종 선택

  • Github Actions을 이용한 CI
    • develop, main 브랜치에 push, pull request 등 변경이 가해지는 경우 자동으로 테스트를 실행한다.
  • Github Actions와 Jenkins를 이용한 CD
    • develop, main 브랜치에 push, merge되는 경우 Github Actions가 이를 감지하여 jenkins에게 알린다.
    • Jenkins는 코드를 clone받아 빌드를 진행한다.
    • 빌드된 jar 파일을 scp를 통해 전송하고, 배포 script를 실행시킨다.

Jenkins 적용

  • 처음에는 Publish Over SSH 플러그인을 사용

    • 해당 플러그인이 보안 이슈로 22년 초에 지원이 종료되었음을 확인
    • 관련 링크
  • Pipeline 방식을 통해 설정하기로 변경

  • SSH Agent 플러그인을 사용해서 배포 서버와 ssh 통신

  • 상대경로로하니 적용되지 않는 경우도 있었다... 웬만하면 다 절대경로로 지정하자

  • monorepo 이었기 때문에, 추가적인 경로 설정이 필요했다. (backend/reviewduck)

  • jenkins 스크립트

    pipeline {
        agent any
        tools {
            nodejs "ReviewDuckFront"
        }
        
        stages {
            stage('github clone') {
                steps{
                   git branch: 'develop', 
                   credentialsId: 'review-duck-credential', 
                   url: 'https://github.com/woowacourse-teams/2022-review-duck'
                }
            }
            
                    
            stage('test'){
                steps{
                    dir('backend/reviewduck'){
                        sh "./gradlew test"
                    }
                }
            }
            
            stage('backend build'){
                steps{
                    dir('backend/reviewduck'){
                        sh'''
                            echo build start
                            ./gradlew clean bootJar
                        '''
                    }
                }
            }
            
            stage('frontend build'){
                steps{
                    dir('frontend'){
                        sh '''
                        yarn install
                        yarn run build
                        '''
                    }
                }
            }
            
            stage('Backend Deploy') {
                steps{
                    dir('backend/reviewduck'){
                        sshagent(credentials : ['develop']) { # credential Id와 동일하게 맞춘다.
                            sh 'ssh -o StrictHostKeyChecking=no ubuntu@{ip 주소} uptime'
                            sh 'ssh -v ubuntu@{ip 주소}'
                            sh 'scp build/libs/*.jar ubuntu@{ip 주소}:/home/ubuntu/deploy'
                            sh 'ssh ubuntu@{ip 주소} "bash /home/ubuntu/deploy/deploy.sh"'
                        }
                    }
                }
            }
            
            stage('Frontend Deploy'){
                steps{
                    dir('frontend'){ 
                        sshagent(credentials : ['develop']) {
                            sh 'ssh -o StrictHostKeyChecking=no ubuntu@{ip 주소} uptime'
                            sh 'ssh -v ubuntu@{ip 주소}'
                            sh 'scp -r build/* ubuntu@{ip 주소}:/home/ubuntu/deploy/develop'
                        }
                    }
                }
            }
        }
    }
  • 배포 스크립트

    #!/bin/bash
    PROJECT_NAME=reviewduck
    
    echo "> 현재 구동중인 애플리케이션 pid 확인"
    CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
    
    echo "> 현재 구동중인 애플리케이션 pid: $CURRENT_PID"
    if [ -z "$CURRENT_PID" ]; then
            echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
    else
            echo "> kill -15 $CURRENT_PID"
            kill -15 $CURRENT_PID
            sleep 15
    fi
    
    echo "chmod +x jar 변경"
    chmod +x /home/ubuntu/deploy/reviewduck-0.0.1-SNAPSHOT.jar
    
    echo "서버 실행"
    nohup java -jar /home/ubuntu/deploy/reviewduck-0.0.1-SNAPSHOT.jar 1> /dev/null 2>&1  &
    
    #echo "shell script 종료"
    #exit
Clone this wiki locally