Jenkins + Docker CI/CD 구축 과정

yeong-min·2025년 1월 7일
0

문제 상황

MSA 구조로 총 5개의 서버를 운영하다 보니, 서버의 코드를 수정할 때마다 GitHub에 코드 푸시, Docker 이미지 패키징, 서버에서 이미지 가져오기, 그리고 Docker-Compose 재실행 작업을 반복해야 했습니다. 이 과정이 개발 작업 시간을 지연시켜, 자동화가 필요했습니다.

Docker와 Jenkins를 이용해서 CI/CD 자동화 시스템을 구축해보자!

1. Jenkins

1.1 Jenkins란?

Jenkins는 오픈 소스 자동화 서버로서, 소프트웨어 개발과 배포 프로세스를 자동화하는 데 사용됩니다. CI/CD(Continuous Integration/Continuous Deployment) 파이프라인의 핵심 구성 요소로서, 개발자들이 코드 변경 사항을 지속적으로 통합하고 배포할 수 있도록 도와줍니다.

1.2 CI (Continuous Integration)

a. 소스 코드 가져오기 (Pull Source)
b. 프로젝트 빌드 (Build Project)
c. Docker 이미지 푸시 (Push Docker Image)

1.3 CD (Continuous Deployment)

a. 배포 요청 (CD Request)
b. 이미지 가져오기 (Pull Image)
c. 배포 (Deploy)


2. Jenkins 프로젝트에 적용하기

2.1 젠킨스 이미지 다운로드

이미지를 다운로드합니다.

다운로드를 확인합니다.

[명령어 설명]
docker run -d -p 9090:8080 -v /jenkins:/var/jenkins_home --name jenkins -u root jenkins/Jenkins

  • -d
    이 옵션은 컨테이너를 백그라운드에서 실행하도록 설정

  • -p
    포트 매핑 옵션입니다. 왼쪽의 포트 번호는 호스트(외부) 포트 번호이고, 오른쪽의 포트 번호는 컨테이너 내부의 포트 번호

  • -v
    볼륨 마운트 옵션입니다. 이 옵션은 호스트와 컨테이너 간의 디렉토리 공유를 설정

Jenkins가 실행중인 것을 확인할 수 있습니다.


2.2 Jenkins에서 Github 연결

global 클릭

Credential을 등록해줍니다.


2.3 Github에서 Jenkins 연동

Repository에서 Settings > Webhooks

Webhooks을 연결해줍니다.

  1. GitHub 계정에 로그인합니다.

  2. 오른쪽 상단의 프로필 아이콘을 클릭한 후, 드롭다운 메뉴에서 Settings를 선택합니다.

  3. 설정 페이지의 왼쪽 사이드바에서 Developer settings를 클릭합니다.

  4. Personal access tokens 메뉴를 선택하고 Generate new token 버튼을 클릭합니다.

  5. 토큰에 이름과 필요한 권한을 지정한 후, Generate token 버튼을 클릭하여 새로운 토큰을
    생성합니다.

  6. 필요한 권한
    repo : 리포지토리에 접근하고 조작할 수 있는 권한입니다.
    admin:repo_hook : 리포지토리 웹훅을 관리할 수 있는 권한입니다.


2.4 Jenkins Pipeline 생성

Jenkins home -> 새로운 item -> pipeline -> 이름 설정

Build Triggers 부분에 Github의 Webhook 기능이 활성화 될 수 있도록 체크합니다.


2.5 SSH 연동

Jenkins 홈 -> Jenkins 관리 -> system

SSH를 연결해줍니다.

  • Jenkins 설정
    Jenkins 홈 -> 관리 -> 시스템 설정 : Jenkins 홈 화면에서 Manage Jenkins를 클릭한 후,Configure System을 선택합니다.

  • SSH 키 설정
    상단에 id_rsa 키 값 입력 : 화면 상단에 복사한 id_rsa 키 값을 입력합니다.

  • SSH 설정

    • Name : 식별할 수 있는 임의의 이름을 입력합니다.
    • Hostname : SSH로 배포될 대상 서버의 외부 IP 주소를 입력합니다. SSH 연결을 위해 포트 22번이 포트포워딩을 통해 열려 있어야 합니다.
    • Username : 연결할 서버의 사용자 이름을 입력합니다.
    • Remote Directory : JAR 파일이 배포될 경로를 입력합니다.

2.6 Publish over SSH 파이프라인 작성

[코드 설명]

  • Pipeline
    파이프라인 전체 과정을 포함하는 블록을 정의합니다.
  • agent any
    이 파이프라인이 Jenkins의 어떤 에이전트에서든 실행될 수 있음을 명시합니다.
  • Stages
    여러 단계(stage)로 구성된 작업을 정의하는 부분입니다.
  • stage('github clone')
    github clone'이라는 이름의 첫 번째 단계를 시작합니다. GitHub에서 코드를 복제하는 작업이 이루어집니다.
  • Steps
    각 단계에서 수행할 구체적인 명령들을 정의합니다.
  • Git
    Git 명령어를 사용하여 지정된 브랜치('main')에서 코드를 복제합니다. 이때 'jenkins-ss-server'라는 인증 정보를 사용하고, 주어진 URL에서 리포지토리를 복제합니다.
  • stage('build')
    'build'라는 이름의 두 번째 단계로, 빌드 작업을 수행합니다.
  • Sh
    Shell 스크립트를 실행하여 Gradle 래퍼 파일에 실행 권한을 부여하고, 'clean bootJar' 작업을 통해 빌드를 수행합니다.
  • stage('deploy')
    deploy라는 이름의 세 번째 단계로, 배포 작업을 수행합니다.
  • sshPublisher
    • SSH를 통해 파일을 원격 서버로 전송하고 원격 명령을 실행합니다.
    • /project/server 디렉토리에 jar 파일을 전송하고, 'bb-server.sh' 스크립트를 실행합니다.

실행되고 있는 애플리케이션이 있다면 종료하고 다시 배포한다는 내용

  • /deploy/ 디렉토리 내에서 가장 최근에 수정된 JAR 파일을 찾아서 그 경로를 JAR_PATH 변수에 저장합니다.
  • nohup을 사용하여 터미널 세션이 종료되어도 Java 애플리케이션을 백그라운드에서 계속 실행할 수 있도록 하고, java -jar로 JAR 파일을 실행합니다.
  • 실행할 때, 서버 포트(8080)와 스프링 프로파일(dev)을 설정합니다.
  • 표준 출력과 표준 에러를 /dev/null로 리다이렉션하여 콘솔에 로그가 출력되지 않게 합니다.

2.7 빌드하기

Jenkins 홈 -> Jenkins-ss-server 클릭 -> 지금 빌드 클릭 -> 빌드 성공

/home/ubuntu 디렉토리에 project라는 폴더가 생기고 위의 설정한 /project/server 경로에 .jar파일이 생성된 것을 볼 수 있습니다.


2.8 Docker와 Jenkins 연결

설치할 플러그인

  1. Docker Plugin
    Jenkins를 Docker와 통합하여 Docker 컨테이너를 관리하고 실행할 수 있도록 해줍니다.
  2. Docker API Plugin
    다른 플러그인에서 Docker와 상호작용할 수 있도록 Docker Java API를 제공합니다.
  3. Docker Commons Plugin
    여러 Docker 관련 플러그인에서 공통적으로 사용하는 기능을 제공합니다.
  4. Docker Pipeline
    Jenkins 파이프라인 스크립트에서 Docker 컨테이너를 빌드하고 사용할 수 있게 해줍니다.

도커허브에서 토큰 발급합니다.

Multibranch Pipeline 생성

Github credential을 누르고, github주소를 입력합니다.

Jenkins 파일 설명

  1. Set Executable Permissions 단계
    sh 'chmod +x gradlew': gradlew 파일에 실행 권한을 부여합니다.

  2. Gradle Build 단계
    sh './gradlew clean build': Gradle을 사용하여 프로젝트를 클린 빌드합니다.

  3. Docker Build 단계
    dockerImage = docker.build repository + ":$BUILD_NUMBER": Docker 이미지를 빌드하고, 태그를 repository:빌드 번호 형식으로 지정합니다. 빌드된 Docker 이미지 객체는 dockerImage 변수에 저장됩니다.

  4. Login 단계
    sh 'echo $DOCKERHUB_CREDENTIALS_PSW | docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin': Docker Hub에 로그인합니다. 환경 변수 DOCKERHUB_CREDENTIALS_USR와 DOCKERHUB_CREDENTIALS_PSW를 사용하여 자격 증명을 전달합니다.

  5. Push 단계
    sh 'docker push repository:repository:BUILD_NUMBER': 빌드된 Docker 이미지를 Docker Hub 리포지토리에 푸시합니다.


2.9 젠킨스 적용 확인

프로젝트에 사용할 bb-server를 docker-compose 파일로 올리고 실행하였습니다.

젠킨스와 mariadb, bb-server가 실행되고 있는 것을 보실 수가 있습니다.

  1. ssh -L 8090:localhost:8090 ubuntu@172.25.235.177 포트포워딩을 시도합니다.
  2. bb-server의 board/list에 접근합니다.

bb-server를 수정해보겠습니다. HelloWorld를 반환하는 컨트롤러를 추가하였습니다.


깃허브에 푸시합니다.


Jenkins Pipeline 단계가 정상적으로 실행됩니다.

push전에는 99koo/bb-server가 하나이지만

  1. 젠킨스 완료 후에 TAG가 18로 하나가 더 생성되었습니다.
  2. 이 후 0.0.2에 Tag 18을 덮어쓰기 한 후 docker compose up -d 명령어를 수행합니
    다.

변경된 내용이 적용되는 것을 확인할 수 있습니다.

총 5개 서버 중 제가 작업중인 세개의 서버를 연결하여 MSA 프로젝트에 적용중입니다.

0개의 댓글