본문 바로가기
우리 FISA

우리FISA 클라우드 서비스 개발 - 프로젝트 시작 전 CI/CD 파이프라인 만들기

by dvid 2023. 8. 20.

Jenkins & docker CI/CD 파이프라인

지난 포스팅에서는 docker 위에서 실행되는 Jenkins를 활용해서 Spring Boot 애플리케이션을 배포했다.

이번에는 Jenkins환경은 같지만, Docker에서 실행되는 Spring Boot 어플리케이션에 대해서 CI/CD 파이프라인을 구축해 보겠다.

EC2 서버에 Docker 설치

Docker

sudo apt-get update

sudo apt-get install ca-certificates curl gnupg

sudo install -m 0755 -d /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker Engine

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo chmod 006 /var/run/docker.sock

docker -v

Docker에서 Jenkins 설치 및 실행

Jenkins 설치

docker pull jenkins/jenkins:jdk11

docker images

ubuntu@ip-172-31-12-140:~$ docker images
REPOSITORY        TAG       IMAGE ID       CREATED      SIZE
jenkins/jenkins   jdk11     541ec44c40ea   5 days ago   463MB

Jenkins 실행

docker run -d \
--name jenkins \
-p 80:8080 \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:jdk11
  • -d: detached mode로 실행 (백그라운드)
  • --name: 컨테이너 이름 지정
  • -v: 호스트와 컨테이너 간 디렉터리 또는 파일 매핑 설정

Spring boot Jenkins 파이프라인 생성

Jenkinsfile

pipeline {

    agent any

    stages {
        stage('Git clone') {

            steps {
                git branch: '${branchName}', 
                url: '${repository url.git}'
            }
        }

        stage ("build") {

            steps {
                sh "chmod +x gradlew"
                sh "cp ../settings/application.yml src/main/resources"
                sh "./gradlew clean build"
            }
        }

        stage ("docker login") {
            steps {
                sh "echo $DOCKER_HUB_PASSWORD | docker login -u $DOCKER_HUB_USERNAME --password-stdin" 
            }
        }

        stage ("docker build") {
            steps {
                sh "docker build . -t {dockerhubUsername/imageName:tag}"
            }
        }

        stage ("docker push") {
            steps {
                sh "docker push {dockerhubUsername/imageName:tag}"
            }
        }

        stage ("docker clear") {
            steps {
                sh "docker rmi {dockerhubUsername/imageName:tag}"
            }
        }

        stage ("docker clear") {
            sshagent(credentials: ['server-access-key']) {
                    sh '''
                        ssh -o StrictHostKeyChecking=no ubuntu@{스프링부트 서버 IP주소} uptime
                        ssh -t ubuntu@{스프링부트 서버 IP주소} echo $DOCKER_HUB_PASSWORD | docker login -u $DOCKER_HUB_USERNAME --password-stdin
                        ssh -t ubuntu@{스프링부트 서버 IP주소} chmod +x ./deploy.sh
                        ssh -t ubuntu@{스프링부트 서버 IP주소} ./deploy.sh
                    '''
                }
        }
    }
}

 

중간의 DOCKER_HUB_~는 내가 설정한 환경변수이다.
Jenkins관리 -> System 이동 후 중간쯤 Global properties에서 설정해 주면 된다.

 

deploy.sh

 !#/bin/bash

docker pull iwasacar/iwasacar-server
docker run -d --name iwasacar-server -p 80:8080 iwasacar/iwasacar-server

docker hub에 push 된 image를 pull 받아 실행해 주면 된다.

 

사실 현재는 repository가 public이라 쉽게 배포했지만, private 환경에서 ssh를 통해 clone을 받으려니 잘 되지 않았다. 꼭 해결하고 싶은 이슈이다.

 

그리고 운영서버와 개발서버를 나눠 운영할 때도 branch를 어떻게 관리할지 고민해 봐야겠다.

 

Vue.js Jenkins 파이프라인 생성

pipeline {
    agent any
    tools {nodejs 'Node18'}
    
    stages {
        stage('git clone') {
            steps {
                git branch: 'main', 
                url: '${github repository url.git}'
            }
        }
        stage('build'){
            steps {
                sh '''
                     npm install
                     npm run build
                 '''
            }
        }
        stage('deploy'){
            steps{
                sshagent(credentials:['vue server access key']){
                    sh '''
                        tar -cf dist.tar dist
                        ssh -o StrictHostKeyChecking=no ubuntu@{vue server ip} uptime
                        scp dist.tar ubuntu@{vue server ip}:/home/ubuntu
                        ssh -t ubuntu@{vue server ip} chmod +x ./deploy.sh
                        ssh -t ubuntu@{vue server ip} ./deploy.sh
                    '''
                }
            }
        }
    }
}

Vue js 어플리케이션을 스프링과 다르게 정적 파일을 Nginx를 통해 서빙하기 때문에 빌드된 정적 파일을 압축해서 EC2 서버에 배포한다.

 

위 과정에서 두 가지 플러그인을 설치해야한다.

위 두가지 플러그인을 받도록 하자.

 

그 후 두 가지 설정이 필요하다

1. 노드 설정

 

2. ssh를 위한 private키 설정

vue server에 접근할 때 사용하는 pem키를 넣어주자

 

deploy.sh

#!/bin/bash

tar -xf dist.tar
sudo rm -r /var/www/html/dist
sudo mv ./dist /var/www/html

Nginx가 실행되는 프론트 서버에 위 스크립트를 적절한 경로에 저장하자.

 

정리

위와 같이 프론트엔드와 백엔드 CI/CD 파이프라인을 만들어봤다.

 

그렇지만 아직 SSH로 Clone, branch 관리, 무중단 배포 등 해결할 문제가 조금 남았다.

배포를 완벽하게 하고 개발도 어느정도 궤도에 오르면 이슈를 하나씩 해결해야겠다.

댓글