
CI/CD 구축하는 프로세스는 다음과 같다.
Github Push - WebHook trigger - Jenkinsfile - Git Repo Pull - Project Build - Docker Image - Run Docker Container
+) 젠킨스에 privatge repo를 연결하는 경우 아래 참고
링크텍스트
+) 특정 브랜치에만 trigger 받기
[jenkins]
Generic Webhook Trigger Jenkins Plugin install
PipeLine-Configuration 내
github project check
Generic Webhook Trigger check
Post content Param Expression = $.ref
JSONPath check
Token 임의의 값으로 입력
Optional filter Expression = refs/heads/main
Text = $branch
GitHub hook trigger ~ polling check
[webhook]
Payload URL = [jenkins URL]/generic-webhook-trigger/invoke?token=[위 임의 설정한 토큰]
Content type = application/json
Just the push event check
젠킨스 설치
docker run \
--name jenkins_1 \
-p 8081:8080 \
-e TZ=Asia/Seoul \
-v /docker_projects/jenkins_1/var/jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /docker_projects/jenkins_1/data:/data \
-u root \
-d \
--restart unless-stopped \
jenkins/jenkins:jdk17
젠킨스 컨테이너 내 도커 설치 - 도커 명령을 사용하기 위함
apt-get update -y
apt-get install -y ca-certificates curl gnupg lsb-release
mkdir -p /etc/apt/keyrings
rm /etc/apt/keyrings/docker.gpg
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli docker-compose-plugin
exit
스프링부트 Jenkinsfile(default)
pipeline {
agent any
environment {
timestamp = "${System.currentTimeMillis() / 1000L}"
}
stages {
stage('Prepare') {
steps {
script {
// Get the ID of the sbb:latest image
def oldImageId = sh(script: "docker images shop-boot-demo:latest -q", returnStdout: true).trim()
env.oldImageId = oldImageId
}
git branch: 'main',
// private repo인 경우
// credentialsId: 'id';
// id는 jenkins - setting - credentials에 username with password로 github에서 발급된 token secret 등록
url: 'https://github.com/sodanhyun/shop-boot-demo'
}
post {
success {
sh 'echo "Successfully Cloned Repository"'
}
failure {
sh 'echo "Fail Cloned Repository"'
}
}
}
stage('Build Gradle') {
steps {
dir('.') {
sh """
chmod +x gradlew
"""
}
dir('.') {
sh """
./gradlew clean bootjar
"""
}
}
post {
success {
sh 'echo "Successfully Build Gradle Test"'
}
failure {
sh 'echo "Fail Build Gradle Test"'
}
}
}
stage('Build Docker Image') {
steps {
script {
sh "docker build -t shop-boot-demo:${timestamp} ."
}
}
}
stage('Run Docker Container') {
steps {
script {
// Check if the container is already running
def isRunning = sh(script: "docker ps -q -f name=shop-boot-demo", returnStdout: true).trim()
if (isRunning) {
sh "docker rm -f shop-boot-demo"
}
// Run the new container
try {
sh """
docker run \
--name=shop-boot-demo \
-p 8080:8080 \
-v /docker_projects/shop-boot-demo/volumes/gen:/gen \
--restart unless-stopped \
-e TZ=Asia/Seoul \
-d \
shop-boot-demo:${timestamp}
"""
} catch (Exception e) {
// If the container failed to run, remove it and the image
isRunning = sh(script: "docker ps -q -f name=shop-boot-demo", returnStdout: true).trim()
if (isRunning) {
sh "docker rm -f shop-boot-demo"
}
def imageExists = sh(script: "docker images -q shop-boot-demo:${timestamp}", returnStdout: true).trim()
if (imageExists) {
sh "docker rmi shop-boot-demo:${timestamp}"
}
error("Failed to run the Docker container.")
}
// If there's an existing 'latest' image, remove it
def latestExists = sh(script: "docker images -q shop-boot-demo:latest", returnStdout: true).trim()
if (latestExists) {
sh "docker rmi shop-boot-demo:latest"
if(!oldImageId.isEmpty()) {
sh "docker rmi ${oldImageId}"
}
}
// Tag the new image as 'latest'
sh "docker tag shop-boot-demo:${env.timestamp} shop-boot-demo:latest"
}
}
}
}
}
리액트
pipeline {
agent any
environment {
timestamp = "${System.currentTimeMillis() / 1000L}"
}
stages {
stage('Prepare') {
steps {
script {
// Get the ID of the sbb:latest image
def oldImageId = sh(script: "docker images fe_wqproject:latest -q", returnStdout: true).trim()
env.oldImageId = oldImageId
}
git branch: 'main',
url: 'https://github.com/sodanhyun/wqproject-fe'
}
post {
success {
sh 'echo "Successfully Cloned Repository"'
}
failure {
sh 'echo "Fail Cloned Repository"'
}
}
}
stage('Build') {
steps {
dir('.') {
sh """
npm install
"""
}
dir('.') {
sh """
CI=false npm run build
"""
}
}
post {
success {
sh 'echo "Successfully Build Test"'
}
failure {
sh 'echo "Fail Build Test"'
}
}
}
stage('Docker Build') {
steps {
sh 'docker build -t fe_wqproject:${timestamp} .'
}
}
stage('Run Docker Container') {
steps {
script {
// Check if the container is already running
def isRunning = sh(script: "docker ps -q -f name=fe_wqproject", returnStdout: true).trim()
if (isRunning) {
sh "docker rm -f fe_wqproject"
}
// Run the new container
try {
sh """
docker run \
--name=fe_wqproject \
-p 82:80 \
-v /docker_projects/wqproejct-fe/volumes/gen:/gen \
--restart unless-stopped \
--network application \
-e TZ=Asia/Seoul \
-d \
fe_wqproject:${timestamp}
"""
} catch (Exception e) {
// If the container failed to run, remove it and the image
isRunning = sh(script: "docker ps -q -f name=fe_wqproject", returnStdout: true).trim()
if (isRunning) {
sh "docker rm -f fe_wqproject"
}
def imageExists = sh(script: "docker images -q fe_wqproject:${timestamp}", returnStdout: true).trim()
if (imageExists) {
sh "docker rmi fe_wqproject:${timestamp}"
}
error("Failed to run the Docker container.")
}
// If there's an existing 'latest' image, remove it
def latestExists = sh(script: "docker images -q fe_wqproject:latest", returnStdout: true).trim()
if (latestExists) {
sh "docker rmi fe_wqproject:latest"
if(!oldImageId.isEmpty()) {
sh "docker rmi ${oldImageId}"
}
}
// Tag the new image as 'latest'
sh "docker tag fe_wqproject:${env.timestamp} fe_wqproject:latest"
}
}
}
}
}