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 ์ฒดํฌ

    • personal token

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