[시즌2] 개인서버 개발/시즌2 설계(완)

Gradle Docker build (feat. Jenkins CI/CD)

북극곰은콜라 2023. 12. 22. 08:01
반응형


개요

Jenkins에 CI / CD를 구성하는 작업은
신규 프로젝트 생성시마다 해줘야하는 귀찮은 작업 중 하나다.
또한 개발 / 배포 환경 상 자주 바뀌는 부분도 없고, 대부분 비슷하게 동작한다.
이러한 공통부분을 묶어서, 하나의 CI / CD로 모든 project (gradle subproject)를 빌드 배포할 수 있도록 구성하려 한다.

 


Gradle docker build

'com.bmuschko.docker-spring-boot-application'는 docker build를 지원하는 gradle plugin이다.
이를 활용하여, gradle의 task를 통해 docker image 생성까지 구성하고자 한다.
docker image 생성을 gradle에서 하는 이유?
기본적으로 docker image 생성 시 project의 name 및 version이 필요하다.
project name은 jenkins에서 argument로 받는다고 해도, gradle의 project.version을 jenkins에서 가져오기에는 복잡하고 효율적이지 않다고 판단했다.
따라서 gradle에서 docker image build까지 담당하는 것이 깔끔할 것이라 판단했다.

gradle-docker-plugin (bmuschko)

docker-spring-boot-application plugin은 4가지 task를 지원한다. (상세 스펙은 reference 참조)
dockerCreateDockerfile
 - dockerfile을 작성할 수 있도록 도와주는 task이다.
 - springBootApplication Object로 baseImage, jvmArgs등을 설정할 수 있도록 도와준다.
dockerBuildImage
 - docker Image를 build하는 task이다. 
 - dependsOn(dockerCreateDockerfile)이며 앞 task에서 생성되는 Dockerfile을 기반으로 docker image를 build한다.
docker {
    springBootApplication {
        baseImage = 'openjdk:8-alpine'
        ports = [9090, 8080]
        images = ['awesome-spring-boot:1.115', 'awesome-spring-boot:latest']
        jvmArgs = ['-Dspring.profiles.active=production', '-Xmx2048m']
    }
}
Guild에 나오는 간단 세팅이다.
기본적으로 SpringBootApplication annotation을 찾아서 main으로 세팅하고
부가적인 정보를 springBootApplication Object로 받아서 추가한다.

Read yml in gradle docker task

[root] gradle.build

import org.yaml.snakeyaml.Yaml

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath('org.yaml:snakeyaml:2.0')
    }
}

plugins {
    id 'com.bmuschko.docker-spring-boot-application' version '9.4.0'
}

...

subprojects {
    ...

    docker {
        dockerCreateDockerfile.doFirst {
            def appConfig = new Yaml().load( project.file('src/main/resources/application.yml').newInputStream() )
            springBootApplication {
                baseImage = 'openjdk:17'
                ports = [appConfig.server.port, appConfig.server.port]
                images = ["${project.name}:${project.version}", "${project.name}:latest"]
                jvmArgs = ['-Dspring.profiles.active=release', '-Duser.timezone=Asia/Seoul']
            }
        }
        dockerBuildImage.dependsOn('build')
    }
}
plugin user guide의 sample code를 그대로 사용하기에는 문제가 있다.
현 project 계획은 root 밑으로 subprojects들이 있고 jenkins에서 ci / cd의 task에 subproject를 지정하여 빌드 및 배포를 하려한다.
따라서 예시처럼, 각 build.gradle마다 port 등 을 지정하는 방식은 쓸 수 없다.
task 실행 시점에 해당 프로젝트의 설정을 읽어오는 방식으로 적용하고자 한다.
spring의 application.yml을 읽어서 server.port 값을 세팅하도록 설정했다.
snakeyaml library로 yml을 파싱하여 값을 추출했다.

 


Jenkins CI / CD 구성

CI

build parameter

빌드할 project를 선택할 수 있도록 parameter 구성
프로젝트가 추가될 때 마다. Choices를 추가해주어야 한다...

Build Steps

gradle 레퍼로 실행
build parameter로 dockerBuildImage task execute
이는 clean -> ... -> build -> dockerCreateDockerfile -> dockerBuildImage 순으로 진행된다.

CD

build parameter

CD 역시 build할 project와 버전을 parameter로 받는다.

Build Steps

Jenkins의 Docker Build Plugin으로 로컬 이미지를 컨테이너 run하는 방식
복잡한 구성은 최대한 root의 gradle.build로 빼는 방향으로 develop할 예정

 


Next..

2024에는 각 project들의 호흡을 짧게 가져가려고 한다.
인프라는 기존에 있던, RDB, Kafka, Redis, MongoDB 등을 활용한다.
다음 작업 사항은 각 인프라에 접속하는 정보를 제공하는 provider를 lib에 구현하고자 한다.
이후 프로젝트는 lib를 implementation하여 provider를 통해 접속정보를 포함한 config를 얻을 수 있을 것이다.
이는 신규 프로젝트를 손쉽게 시작할 수 있게 할것이라 기대한다.

 


REFERENCE

https://github.com/bmuschko/gradle-docker-plugin

https://plugins.gradle.org/plugin/com.bmuschko.docker-spring-boot-application

https://bmuschko.github.io/gradle-docker-plugin/current/user-guide/

https://bmuschko.github.io/gradle-docker-plugin/current/user-guide/#spring-boot-plugin-extension

 

 

반응형