ํด๋น ๊ธ์ Jenkins์ Github Webhook์ ์ด์ฉํ CICD ํ์ดํ๋ผ์ธ ๊ตฌ์ฑํ๊ธฐ ์๋ฆฌ์ฆ ์ ๋๋ค. ์์ธํ ์ฌํญ์ ์๋ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์!
๋ง์ฝ ํด๋น ์ค์ต ๋ด์ฉ์ ์ฝ๋๊ฐ ๊ถ๊ธํ๋ค๋ฉด ํ๋ก์ ํธ ๊นํ๋ธ ์์ ํ์ธํ ์ ์์ต๋๋ค.
- 1ํธ ์๋ฆฌ์ฆ๋ฅผ ์์ํ๋ฉฐ :: ์ปจํ ์ธ ๊ฐ์์ ๋๊ธฐ
- 2ํธ ํ๋ก ํธ์๋ ๊ฐ๋ฐํ๊ธฐ :: ๋ฆฌ์กํธ์ axios
- 3ํธ ๋ฐฑ์๋ ๊ฐ๋ฐํ๊ธฐ :: SpringBoot ์ h2
- 4ํธ ec2 ์์ฑ ๋ฐ Jenkins ์ค์น :: AWS EC2๋ก Jenkins ์๋ฒ ๋ง๋ค๊ธฐ
- 5ํธ Dockerizing ๋ฐ Nginx ์ค์ :: ๋ฐฐํฌ๋ฅผ ์ํ ๋์ปค ๋น๋์ Nginx์ ๋ฆฌ๋ฒ์ค ํ๋ก์
- 6ํธ ์นํ ์ค์ ํ๊ธฐ :: Github Webhook ์ฐ๋ํ๊ธฐ
- 7ํธ pipeline์ผ๋ก ๋ฐฐํฌํ๊ธฐ :: Jenkins Pipeline Script ์์ฑํ๊ธฐ
์ด์ ์ด Jenkins์ ๋ง์ง๋ง ์๊ฐ์ด ๋์๋ค.
์ง๋ ์๊ฐ๊น์ง Continous Integration ์ ์ํํ์ผ๋ ์ด์ ๋ Continous Deploy๋ฅผ ์ํํด๋ณด์!
๋ชฉ์ฐจ
- jenkins์ pipeline ์์ฑํ๊ธฐ
- item ์ถ๊ฐ
- ์ค์ ๋ฐ script ์์ฑ
- ํ ์คํธ
1. Jenkins์ Pipeline ์์ฑํ๊ธฐ
์ ํจ์ค์ Pipeline ์ ์ฐ์์ ์ธ ์ด๋ฒคํธ & Job ๊ทธ๋ฃน์ ์๋ฏธํ๋ค.
์ฐ๋ฆฌ๊ฐ ๋ง์ฝ ๋ฐฐํฌํด์ผํ ์ฌ๋ฌ Application ์ด๋ ๊ด๋ฆฌํด์ผํ ์์์ด ์๋ค๋ฉด Pipeline Script๋ฅผ ์คํํจ์ผ๋ก ๊ธฐ๋ํ ๋ชฉ์ ์ ์ด๋ฃฌ๋ค.
์ฆ, ์ฐ๋ฆฌ๊ฐ Code Commit ์ ํ๋ค๋ฉด Pipeline ์ด์ฉํด์ Webhooks ๋ฅผ ๊ฐ์ํ๊ณ ์ด๋ฒคํธ๋ฅผ ์คํํ๋ค.
Pipeline Script ์์ ์ฐ๋ฆฌ๊ฐ ํ ๊ฒ๋ค์ ๋ช ์ํด์ฃผ๋๋ฐ, ์ด๋ ํ๋ฒํ Groovy ํํ์ ์ฝ๋ ๋ธ๋ญ์ด๋ผ๊ณ ์๊ฐํด๋ ๋๋ค.
Pipeline ์ ์ ์ธํ ๋๋ ๋ค์๊ณผ ๊ฐ์ด pipeline ๋ธ๋ก ๋ด๋ถ์์ ์ ์ํ๋ค.
pipeline {
// Declarative ์ถ๊ฐ
}
์ด๋ ํญ์ ์ต์์ ๋ ๋ฒจ์์ ๋ค๋ฅธ ๋ธ๋ก๋ค์ ๊ฐ์ธ์ผ ํ๊ณ , ์๋์ ๋ธ๋ก์ด ์ฌ ์ ์๋ค.
- agent
- pipeline ์ต์๋จ์ ์์นํ์ฌ, ํน์ job ๋ค์ ์ํํ agent ๋ฅผ ์๋ฏธํ๋ค
- ๋ํ์ ์ผ๋ก๋ node, docker, kubernetes ๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ํฌํจํ ์ ์๋ค.
- stages
- ํ๋ ์ด์์ stage๋ฅผ ์ ์ํ๋๋ฐ, stage๋ ํด๋น pipeline ์ด ๋์ํ ๋, ์คํ๋๋ ๋จ๊ณ๋ฅผ ์๋ฏธํ๋ค
- ๋ด๋ถ์ ์ผ๋ก steps ๋ฅผ ์ ์ํด์ค์ผ ํ๋ค
- environment
- pipeline ๋ด๋ถ์์ key-value ํํ๋ก ์ฌ์ฉํ ์ ์๋ ํ๊ฒฝ ๋ณ์์ด๋ค.
- parameters
- pipeline ๋ด๋ถ์์ ํน์ ๋ ธ๋, ์ปจํ ์ด๋๋ฅผ ์คํ์ํฌ ๋ ๋ณ์๋ฅผ ์ ๊ณตํด์ผํ ๋ ์ฌ์ฉํ๋ค.
์ด ๊ฐ๋ ๋ค์ ๊ฐ์ง๊ณ pipeline ์ ๊ตฌ์ฑํด๋ณด์!
Pipeline Item ์ถ๊ฐํ๊ธฐ
Jenkins ๋์๋ณด๋๋ก ๋ค์ด๊ฐ์ ๋ค์ ์๋ก์ด Item ์ ๋ง๋ค๊ณ ์ด๋ฒ์๋ Pipeline Item์ ์ถ๊ฐํ์.
์ญ์ Github ํ๋ก์ ํธ๋ฅผ ์ ํํ ๋ค, Github Repository์ URL์ ์ ์ด์ฃผ์.
๊ทธ๋ฆฌ๊ณ Pipeline speed/durability ์์๋ Performance-optimized ๋ก ์ค์ ํด์ฃผ๊ณ Build Trigger๋ฅผ Github hook trigger for GitScm Polling ์ผ๋ก ์ฒดํฌํ์
Pipeline Script ์์ฑํ๊ธฐ
jenkins pipeline ์ ์ถ๊ฐํ ๋, ์๋์ pipeline script ํญ๋ชฉ์์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ์
pipeline {
agent any
options {
timeout(time: 1, unit: 'HOURS')
}
environment {
SOURCECODE_JENKINS_CREDENTIAL_ID = 'jenking-github-wh'
SOURCE_CODE_URL = 'https://github.com/my-research/todo-with-cicd.git'
RELEASE_BRANCH = 'master'
}
stages {
stage('Init') {
steps {
echo 'clear'
sh 'docker stop $(docker ps -aq)'
sh 'docker rm $(docker ps -aq)'
deleteDir()
}
}
stage('clone') {
steps {
git url: "$SOURCE_CODE_URL",
branch: "$RELEASE_BRANCH",
credentialsId: "$SOURCECODE_JENKINS_CREDENTIAL_ID"
sh "ls -al"
}
}
stage('frontend dockerizing') {
steps {
sh "docker build -t todo/frontend ./frontend"
}
}
stage('backend dockerizing') {
steps {
sh "pwd"
dir("./backend"){
sh "pwd"
sh "gradle clean"
sh "gradle bootJar"
sh "docker build -t todo/backend ."
}
}
}
stage('deploy') {
steps {
sh '''
docker run -d -p 5000:5000 todo/frontend
docker run -d -p 8080:8080 todo/backend
'''
}
}
}
}
์ด๋ฅผ ํด์ํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ต์ด์ agent ๋ any๋ก ์ค์ ํด์ ๋ชจ๋ ์์ ์ ์ปค๋ฒํ ์ ์๋๋ก ํ๊ณ , environment ์์๋ ์ฐ๋ฆฌ๊ฐ git clone ์ ํ ๋, ํ์ํ ์ฌ๋ฌ ์ ๋ณด๋ค์ ์ํด ์ ์ํด์คฌ๋ค.
Init ๋จ๊ณ์์๋ ๊ธฐ์กด์ docker ๊ฐ ๋์์ ธ ์๋ค๋ฉด ๋ชจ๋ ๋์ปค๋ฅผ ๊บผ์ค๋ค.
๊ทธ๋ฆฌ๊ณ Frontend Dockerizing ์ด๋ผ๋ stage ์์ clone ํ ๋๋ ํ ๋ฆฌ์ ์์นํ Dockerfile ๋ค์ ์ด์ฉํด Docker build ๋ฅผ ์ํํ๋ค.
๊ทธ ๋ค์ Backend Dockerizing ์ด๋ผ๋ stage ์์๋ ์ฐ๋ฆฌ๊ฐ clone ํ spring boot project ๋ฅผ build ํ๋๋ฐ, ๋น๋์ ์ฑ๊ณตํ๋ฉด dockerizing ์ ์ํํ๋ค.
๊ทธ๋ฆฌ๊ณ deploy ๋ผ๋ stage ์์ ์ฐ๋ฆฌ์ ๋์ปค ์ด๋ฏธ์ง๋ค์ ๊ฐ๊ฐ์ port ์ ๋ง๊ฒ ํฌ์๋ฉ ํ ํ run ๋ช ๋ น์ด๋ฅผ ํตํด์ ์คํ์ ํ๊ฒ ๋๋ค.
ํด๋น ๋ด์ฉ์ ์ ์ฅํ๊ณ ๋์์ Build Now ๋ฅผ ํด๋ฆญํ์!
๊ทธ๋ผ ๋ค์๊ณผ ๊ฐ์ด Build์ ์ฑ๊ณตํ๊ณ ์ฐ๋ฆฌ๊ฐ Pipeline ์ ๋ช ์ํด๋์ ๊ณผ์ ์ ์ํํ์ฌ ์ฑ๊ณต์ ์ผ๋ก Job์ ์คํํ์๋ค.
์ด์ ๋ง์ง๋ง์ผ๋ก ํ ์คํธ๋ฅผ ์ํํด๋ณด์!
2. ํ ์คํธ
์ฐ๋ฆฌ๊ฐ ์ฌ์ ์ ์ค๋นํด๋์ Nginx๋ฅผ ํตํด์ EC2 ์ 80 ํฌํธ๋ก ์ ์ํ๋ฉด 5000ํฌํธ์ ๋์ปค๋ก ์ ์ํ๊ฒ ๋์ด์ ์๋์ ํ๋ก ํธ์๋ ์๋น์ค๊ฐ ์ ๋์ค๋ ๊ฒ์ ์ ์ ์๋ค.
ํ์ง๋ง ๋ฌธ์ ๊ฐ ์๋ค!
์ฐ๋ฆฌ๊ฐ ํ๋ก ํธ์๋์ ์ ์ํ๋ฉด ์ง๋ ์๊ฐ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ import.sql ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐฑ์๋๋ก๋ถํฐ ๋ฐ์์์ผ ํ๋ค
ํ์ง๋ง ๋ณด์ด๋๊ฒ ์ฒ๋ผ ๋ฐ์์ค์ง ์๋๋ค.
ํ์ฌ ํ๋ก ํธ์๋๊ฐ API ํธ์ถ์ ๋ณด๋ด๋ ๊ณณ์ ํ์ธํด๋ณด์
ํ์ฌ ํ๋ก ํธ์๋๋ 127.0.0.1 ์ api/todos๋ก ์์ฒญ์ ๋ณด๋ธ๋ค.
์ฐ๋ฆฌ๋ ํ ์คํธ ํ๊ฒฝ์ธ Local ์์๋ 127.0.0.1๋ก ๋ช ์ํ์ง, ์ค ์๋น์ค๊ฐ ์ด์์ค์ธ ์๋ฒ์ Backend๋ก ์์ฒญ์ ๋ณด๋ด์ผ ํ๋ค.
์ด ๋ฌธ์ ๋ฅผ CICD ํ์ดํ๋ผ์ธ์ ํตํด์ ํด๊ฒฐํด๋ณด์!!
frontend ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํด์ SERVER.js ์ ์๋ API ํธ์ถ ์คํ์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ EC2 ์ธ์คํด์ค์ IP๋ก ๋ณ๊ฒฝํด์ฃผ์
import axios from "axios";
export const SERVER = axios.create({
baseURL: "http://3.38.95.48",
headers: {
"Content-Type": "application/json",
},
});
ํ์ผ์ ์ ์ฅํ๊ณ github๋ก code push๋ฅผ ํ๋ค๋ฉด ์ฐ๋ฆฌ๊ฐ ์ด์ ์ ์์ฑํด๋์ webhooks๊ณผ pipeline script์ ์ํด์ ์๋ก์ด ๋ฒ์ ์ด ์ฆ์ ๋ฐฐํฌ๋ ๊ฒ์ด๋ค!
์จ~
๋๊ธ