Jenkins - πŸš€ λ‘œμ»¬μ—μ„œ jenkins μ—°λ™ν•˜κΈ°

1. λ‘œμ»¬μ—μ„œ Jenkins λ₯Ό λ„μšΈ Dockerfile 을 μ€€λΉ„ν•œλ‹€.

βœ”οΈ Dockerfile-jenkins

FROM jenkins/jenkins:lts-jdk21 # 곡식 Jenkins 이미지 쀑 JDK 21을 μ§€μ›ν•˜λŠ” LTS 버전을 μ‚¬μš©

# ν•„μš”ν•œ 경우, 좔가적인 Jenkins μ„€μ • νŒŒμΌμ΄λ‚˜ ν”ŒλŸ¬κ·ΈμΈμ„ 볡사할 수 μžˆμŠ΅λ‹ˆλ‹€.
# μ˜ˆμ‹œλ‘œ plugins.txt νŒŒμΌμ„ λ³΅μ‚¬ν•˜κ³  ν”ŒλŸ¬κ·ΈμΈμ„ μ„€μΉ˜ν•˜λŠ” 방법은 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.
# COPY plugins.txt /usr/share/jenkins/ref/plugins.txt
# RUN /usr/local/bin/install-plugins.sh < /usr/share/jenkins/ref/plugins.txt

EXPOSE 8080 50000 # (μ˜΅μ…˜) μ»¨ν…Œμ΄λ„ˆ λ‚΄μ—μ„œ μ‚¬μš©ν•  포트λ₯Ό λͺ…μ‹œμ μœΌλ‘œ λ…ΈμΆœν•©λ‹ˆλ‹€.

# 곡식 μ΄λ―Έμ§€μ˜ ENTRYPOINT 및 CMDκ°€ 이미 μ„€μ •λ˜μ–΄ μžˆμœΌλ―€λ‘œ λ³„λ„μ˜ μ‹€ν–‰ λͺ…령은 ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

ν”„λ‘œμ νŠΈκ°€ Java 버전 21을 μ‚¬μš©ν•˜κ³  μžˆμ–΄, JDK21 을 μ§€μ›ν•˜λŠ” Jenkins 이미지λ₯Ό μ‚¬μš©ν•˜μ˜€μŠ΅λ‹ˆλ‹€. κ·Έλ ‡μ§€ μ•Šκ³  일반 Jenkins lts λ²„μ „μ˜ 이미지λ₯Ό μ‚¬μš©ν•˜λ©΄ Java 17 버전이 μ„€μΉ˜λ˜μ–΄μžˆμ–΄, λ³„λ„λ‘œ Java 21을 μ„€μΉ˜ν•˜κ³  κΈ°λ³Έ μ‚¬μš© λ²„μ „μœΌλ‘œ 이미지λ₯Ό μ»€μŠ€ν„°λ§ˆμ΄μ§• ν•΄μ•Ό ν•©λ‹ˆλ‹€. Java 21 버전을 μ‚¬μš©ν•˜λŠ” 방법은 μ•„λž˜μ˜ λΈ”λ‘œκ·Έλ₯Ό μ°Έκ³ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Jenkins JDK 21 installation by Tools

  • Jenkins 관리

  • Tools

  • JDK installations

  • Add JDK

  • Name(jdk21)

  • Install automatically Check

  • Add Installer (JDK 지원 Site : Amazon-site)

  • Extract .zip/tar.gz

jenkins-tools-jdk21

jenkins file μˆ˜μ •

pipeline {
	agent any

    tools {
        jdk ("jdk21")
    }
}

2. [1.] μ—μ„œ λ§Œλ“  Dockerfile 을 μ‚¬μš©ν•˜μ—¬ 이미지 생성

μ—¬κΈ°μ„œλŠ” docker compose νŒŒμΌμ„ μ‚¬μš©ν•˜μ—¬ 이미지λ₯Ό μƒμ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€. docker compose λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ docker run λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•˜μ—¬ 이미지λ₯Ό λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

services:
    jenkins:
    container_name: jenkins-prac-jpa # Jenkins μ»¨ν…Œμ΄λ„ˆλͺ…
    build:
        context: .
        dockerfile: ./Dockerfile-jenkins
    ports:
        - '9081:8080' # 호슀트의 9081 포트λ₯Ό μ»¨ν…Œμ΄λ„ˆμ˜ 9081 ν¬νŠΈμ— λ§€ν•‘(Jenkins μ›Ή UI μ ‘κ·Ό)
        - '50000:50000' # 호슀트의 50000 포트λ₯Ό μ»¨ν…Œμ΄λ„ˆμ˜ 50000 ν¬νŠΈμ— λ§€ν•‘(Jenkins μ—μ΄μ „νŠΈ μ—μ΄μ „νŠΈ 톡신)
    volumes:
        - ./vol-jenkins:/var/jenkins_home # Jenkins μ„€μ •κ³Ό 데이터λ₯Ό 호슀트의 디렉토리에 μ—°κ²°(μ˜μ†μ„± 보μž₯)
        - ./vol-deployment:/var/deployment # λΉŒλ“œ μ‚°μΆœλ¬Ό(jar 파일) 배포 λŒ€μƒ 폴더λ₯Ό 마운트
    networks:
        - my-network # λ™μΌν•œ λ„€νŠΈμ›Œν¬μ— μ—°κ²°ν•˜μ—¬ λ‹€λ₯Έ μ„œλΉ„μŠ€(db λ“±)κ³Ό 톡신
    restart: unless-stopped # μ»¨ν…Œμ΄λ„ˆ 쀑단 μ‹œ μžλ™ μž¬μ‹œμž‘

networks:
  my-network:
    driver: bridge # λΈŒλ¦Ώμ§€ λ„€νŠΈμ›Œν¬ μ‚¬μš©. μ»¨ν…Œμ΄λ„ˆκ°„ κΈ°λ³Έ λ„€νŠΈμ›Œν‚Ή 제곡

3. Jenkins 접속

  • μ—¬κΈ°μ„œλŠ” localhost:9081 둜 포트λ₯Ό λ§€ν•‘ν•˜μ˜€κΈ° λ•Œλ¬Έμ—, http://localhost:9081 둜 μ ‘μ†ν•˜λ©΄, 둜컬 μ  ν‚¨μŠ€ μ»¨ν…Œμ΄λ„ˆμ— 접속할 수 μžˆμŠ΅λ‹ˆλ‹€.

  • Unlock νŽ˜μ΄μ§€λ₯Ό ν’€μ–΄μ€λ‹ˆλ‹€.

    • λΉ„λ°€λ²ˆν˜ΈλŠ” μ»¨ν…Œμ΄λ„ˆμ˜ λ‘œκ·Έμ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

    • λ˜ν•œ, 직접 μ»¨ν…Œμ΄λ„ˆ μ•ˆμ— λ“€μ–΄κ°€μ„œ 확인할 수 도 μžˆμŠ΅λ‹ˆλ‹€.

초기 Unlock νŽ˜μ΄μ§€
초기 λΉ„λ°€λ²ˆν˜Έ

4. μœ μ € 생성

μœ μ €μƒμ„±1
μœ μ €μƒμ„±2
μœ μ €μƒμ„±3

5. ν”ŒλŸ¬κ·ΈμΈ μ„€μΉ˜

ν”ŒλŸ¬κ·ΈμΈ μ„€μΉ˜1
ν”ŒλŸ¬κ·ΈμΈ μ„€μΉ˜2
ν”ŒλŸ¬κ·ΈμΈ μ„€μΉ˜3

πŸ₯² μ  ν‚¨μŠ€κ°€ 자꾸 λ©ˆμΆ”λŠ” ν˜„μƒμ΄ μžˆμŠ΅λ‹ˆλ‹€. λ²„νŠΌμ„ 아무리 클릭해도 먹톡일 λ•ŒλŠ”, κ³ λ―Όν•˜μ§€ 말고 μž¬μ ‘μ† ν•©λ‹ˆλ‹€.

6. New Item -> Pipeline

New Item
  • Item name 을 식별가λŠ₯ν•˜λ„λ‘ μ μ–΄μ€λ‹ˆλ‹€.

  • Pipeline λ₯Ό μ„ νƒν•©λ‹ˆλ‹€.

Pipeline
  • Username with password

  • Scope λŠ” Global λ₯Ό μ„ νƒν•©λ‹ˆλ‹€.

  • Username 은 본인의 Github 아이디λ₯Ό μ μ–΄μ€λ‹ˆλ‹€.

  • Password λŠ” Github μ—μ„œ λ°œκΈ‰λ°›μ€ classic token 을 μ μ–΄μ€λ‹ˆλ‹€.

    • Profile

    • -> Settings

    • -> Developer settings

    • -> Personal access tokens

    • -> Tokens (classic)

    • -> Generate new token

    • μœ νš¨κΈ°κ°„ 없도둝, webhook 체크

7. ngrok

Github Repository 에 setting webhook 으둜 λ“€μ–΄κ°ˆ μ£Όμ†Œλ₯Ό λ“±λ‘ν•΄μ€˜μ•Ό ν•©λ‹ˆλ‹€. 이 λ•Œ localhost λ˜λŠ” 퍼블릭 IP의 port 9081둜 등둝해도, 둜컬 μ  ν‚¨μŠ€ μ»¨ν…Œμ΄λ„ˆλ₯Ό 찾을 수 μ—†μœΌλ―€λ‘œ ngrok λΌλŠ” 것을 μ‚¬μš©ν•˜μ—¬ μ™ΈλΆ€ IPλ₯Ό μž„μ‹œλ‘œ μƒμ„±ν•˜μ—¬ λ“±λ‘ν•©λ‹ˆλ‹€.

7-1. ngrok μ„€μΉ˜

brew install --cask ngrok

7-2. ngrok κ°€μž…

ngrok κ°€μž…ν•˜κΈ°

7-3. ngrok μ‚¬μš©ν•˜μ—¬ μ™ΈλΆ€ IP λ§Œλ“€κΈ°

κ°€μž… ν›„ λ°œκΈ‰λ°›μ€ auth 토큰을 λ³΅μ‚¬ν•˜μ—¬ μ•„λž˜μ™€ 같이 μ»€λ§¨λ“œλ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

ngrok authtoken 20wnvzsRf4Rg3J3lhIpFrXPt49a_*************
# Authtoken saved to configuration file: /Users/your-profile/Library/Application Support/ngrok/ngrok.yml

그리고, localhost:9081 에 λŒ€ν•œ μ™ΈλΆ€ IPλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.

ngrok http 9081
ngrok

μœ„μ—μ„œ μƒμ„±λœ μ™ΈλΆ€ IPλ₯Ό Github Repository Webhook 에 λ“±λ‘ν•©λ‹ˆλ‹€.

github

8. Jenkinsfile μƒμ„±ν•˜μ—¬ 슀크립트 μž‘μ„±ν•˜κΈ°

// Jenkins 둜컬 μ—°μŠ΅μš©
pipeline {
    agent any // λͺ¨λ“  Jenkins μ—μ΄μ „νŠΈμ—μ„œ νŒŒμ΄ν”„λΌμΈ μ‹€ν–‰

    environment {
        // μ»¨ν…Œμ΄λ„ˆ μ›Œν¬μŠ€νŽ˜μ΄μŠ€ λ‚΄μ˜ build μ‚°μΆœλ¬Ό 패슀
        JAR_PATH = 'build/libs/prac-jpa-0.0.1-SNAPSHOT.jar'
        // 둜컬과 마운트 된 μ»¨ν…Œμ΄λ„ˆ 배포 폴더
        DEPLOY_DIR = '/var/deployment'
        // * μ•žμ— / λ₯Ό 뢙이면 루트 폴더 κ²½λ‘œκ°€ 되며, μ•ˆλΆ™μ΄λŠ” 경우 μƒλŒ€ κ²½λ‘œκ°€ λœλ‹€.

        GIT_URL = 'https://github.com/your-profile/<repository-name>.git'
        GIT_BRANCH = 'feature/jenkins-test' # μ›ν•˜λŠ” λŒ€λ‘œ
    }

    stages {
        stage('Check java') {
            steps {
                // Java 버전을 ν™•μΈν•˜μ—¬ ν™˜κ²½μ΄ μ˜¬λ°”λ₯Έμ§€ 검증
                sh 'java -version'
            }
        }

        stage('Checkout') {
            steps {
                script {
                    try {
                        // Git λ ˆν¬μ§€ν† λ¦¬μ—μ„œ μ†ŒμŠ€ μ½”λ“œλ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.
                        git url: env.GIT_URL, branch: env.GIT_BRANCH
                    } catch (e) {
                        print(e)
                    }
                }
            }
        }

        stage('Build & Test') {
            steps {
                // Gradle을 톡해 클린 λΉŒλ“œ 및 ν…ŒμŠ€νŠΈ μ‹€ν–‰
                sh './gradlew clean build'
            }
        }

        stage('check jar') {
            steps {
                // λΉŒλ“œ 결과둜 μƒμ„±λœ jar 파일 λͺ©λ‘ 확인
                sh 'ls -l build/libs'
            }
        }

        stage('scp jar in jenkins container to local') {
            steps {
                // λΉŒλ“œ μ‚°μΆœλ¬Ό jar νŒŒμΌμ„ 배포 λ””λ ‰ν† λ¦¬λ‘œ 볡사. μƒλŒ€ 경둜λ₯Ό μ‚¬μš©ν•΄μ•Ό μ˜¬λ°”λ₯Έ μœ„μΉ˜μ—μ„œ νŒŒμΌμ„ 찾음
                sh "cp ${env.JAR_PATH} ${env.DEPLOY_DIR}/"
            }
        }
    }

    post {
        failure {
            // λΉŒλ“œλ‚˜ 배포 κ³Όμ • 쀑 였λ₯˜κ°€ λ°œμƒν•˜λ©΄ 둜그 λ©”μ‹œμ§€ 좜λ ₯
            echo "Fail to Build or deployment failed. Please check the logs."
        }
    }
}

μœ„μ˜ Jenkinsfile μŠ€ν¬λ¦½νŠΈλŠ” /feature/jenkins-test λΈŒλžœμΉ˜μ— ν‘Έμ‹œλ˜λŠ” μˆœκ°„ μž‘λ™ν•©λ‹ˆλ‹€. ν•΄λ‹Ή 브랜치λ₯Ό jenkins μ»¨ν…Œμ΄λ„ˆμ—μ„œ 체크아웃&λΉŒλ“œν•˜κ³ , μ  ν‚¨μŠ€ μ»¨ν…Œμ΄λ„ˆμ˜ νŠΉμ • 폴더에 λΉŒλ“œ μ‚°μΆœλ¬ΌμΈ jar νŒŒμΌμ„ νŠΉμ • 폴더에 λ³΅μ‚¬ν•©λ‹ˆλ‹€.

νŠΉμ • ν΄λ”λŠ” docker compose μ—μ„œ λ³Όλ₯¨λ§ˆμš΄νŠΈ ν•˜μ—¬, 둜컬 ν΄λ”μ—μ„œλ„ ν•΄λ‹Ή jar νŒŒμΌμ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έ μ™Έ, jar νŒŒμΌμ„ μ‹€ν–‰ λ“±μ˜ 과정은 λ„£μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

λ‹€μŒμ—λŠ” Docker 와 AWS의 EC2/Jenkins λ₯Ό μ‚¬μš©ν•˜μ—¬ CI/CD λ₯Ό ꡬ좕해보둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.

Last updated