A Hands-on Guide to Automated Spring Boot Deployment using GitHub Actions
"k8s 클러스터에 springboot application 배포 시리즈"의 시작 포스팅입니다
이번 포스트에서는 github action으로 springboot application의 docker image를 remote registry에 push 해보도록하겠습니다.
준비사항:
- docker 사용경험
- gradle 사용경험
- docker 계정
node.js 환경에서 개발 및 운영만 해오다보니 로컬 개발환경에서 개발환경에 배포하기 전이나 새로운 시스템을 개발해아할때 Dockerfile로 도커 이미지를 생성해서 AWS ECR이든 Google Container Registry에 도커 이미지를 푸시해서 EKS, GKE에서 사용하는 경우가 대부분이었습니다.
CI tool은 실무에서 가장 많이 사용하며, Github action은 설치 작업이 필요 없고, Jenkins보다 CI단계를 빠르게 수행할 수 있는 Github Action으로 정했습니다.
다루는 내용
- Github action workflow
- secrets
- jib으로 springboot application image 생성하기
- Troubleshooting
Github action workflow
workflow를
프로젝트에 root directory에 .github/workflows/sth.yml 경로로 파일을 생성합니다
해당 파일이 github repository에 main 브랜치가 push가 되면 해당 repository의 actions 탭에 코드로 작성한 workflow가 동작하는것을 확인할 수 있습니다
name: demo workflow
on:
push:
branches:
- main
jobs:
ci-cd-pipeline:
name: ci-cd
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: '17'
- name: Build with Gradle
run: ./gradlew clean build
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build with Gradle and Jib
run: |
./gradlew \
-Djib.to.image=<docker_계정>/<임의선택>:${{ github.sha }} \
jib \
--info \
--stacktrace \
--no-daemon
workflow 설정파일을 push하기전에 workflow를 보면 secrets를 참조하는 코드가 보입니다
github repository에 secrets를 추가해줘야합니다
https://app.docker.com/ docker 계정에서 Personal access token을 생성해줍니다
Scope은 Read & Write로 해주세요. Docker hub에 image를 push할겁니다
Docker Token과 Username을 github repository의 secret에 추가해줍니다
해당 토큰을 github repository > settings > (Security) Secrets and Variables > Actions > New repository secret
DOCKERHUB_USERNAME, DOCKER_TOKEN 토큰을 추가해줍니다
이름은 임의선택입니다
repository에 commit push 하면 workflow가 동작하고 성공적으로 동작하는것을 확인할 수 있습니다
dockerhub의 repository를 확인하시면 해당 계정의 repository에 이미지가 푸시된것을 확인할 수 있습니다
이어서 Jib에 관련된 내용을 살펴보겠습니다
Jib으로 springboot application image 생성하기
jib은 구글에서 oci 표준을 구현한 container image 생성및 관련된 다양한 기능을 제공하는 솔루션입니다
https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin#quickstart
jib/jib-gradle-plugin at master · GoogleContainerTools/jib
🏗 Build container images for your Java applications. - GoogleContainerTools/jib
github.com
gradle을 사용하기 때문에 springboot 빌드 설정파일에 jib 관련 plugin을 설정해줘야 합니다
각 프로젝트마다 gradle, java 등 버전이 다른 부분은 참고해주세요
build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.0.11"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.7.22"
kotlin("plugin.spring") version "1.7.22"
kotlin("plugin.jpa") version "1.7.22"
id("com.google.cloud.tools.jib") version "3.4.3"
}
jib {
from {
image = "eclipse-temurin:17-jre-alpine"
}
to {
image = "<docker계정>/<임의선택>"
}
container {
jvmFlags = arrayOf("-Dspring.profiles.active=local","-Xms3g", "-Xmx3g").toMutableList()
ports = arrayOf("8080").toMutableList()
}
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-batch")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.springframework.kafka:spring-kafka")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("mysql:mysql-connector-java:8.0.33")
runtimeOnly("com.h2database:h2")
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0")
implementation("org.springframework.kafka:spring-kafka")
implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta")
implementation("com.querydsl:querydsl-kotlin:5.0.0")
annotationProcessor("com.querydsl:querydsl-apt:5.0.0:jakarta")
val mockkVersion = "1.13.8"
testImplementation("io.mockk:mockk:${mockkVersion}")
var kotestVersion = "5.8.0"
testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
testImplementation("org.springframework.kafka:spring-kafka-test")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.springframework.batch:spring-batch-test")
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
github action에서 gradle wrapper로 jib 명령어를 수행하지만 커스텀 옵션을 추가했습니다
jib은 container 이미지 생성 뿐만 아니라 image push 기능까지 하기 때문에 image를 push할 이미지 저장소도 입력하는것 같습니다
이미지 저장소는 cloud provider에 각각 syntax가 다르므로 다음 링크를 보고 따라해줍니다
https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin#configuration
jib/jib-gradle-plugin at master · GoogleContainerTools/jib
🏗 Build container images for your Java applications. - GoogleContainerTools/jib
github.com
troubleshooting
Gradle Jib
필자는 jib이란걸 어끄제 알게되어 그동안 Dockerfile로만 springboot application을 배포해왔으나 구글링으로 OCI를 구현한 jib 이란게 있다고 해서 적용해봤습니다
이슈1: gradle jib은 container image를 생성하고 image push까지 해버림
Dockerfile의 경우 docker image만 생성하는것이 전부인데, 이것은 github action에서 자꾸 에러가 발생해서 gradle jib 에 --info, --stacktrace 옵션을 추가하여 디버깅해본결과 docker hub에 대한 권한이 없어서 발생한 이슈였습니다
docker publish access token에 write가 포함되도록 수정해줍니다
에러가 발생한다면 로그 레벨과 stacktrace 옵션을 추가해서 발생하는 이슈에 대해서 파악해야합니다
이슈2: jib은 container image 생성과 push까지 함께 진행합니다
github action job에 push 관련 step을 추가하실 필요가 없습니다
이슈3: latest 이미지 생성안하고 싶으면?
jib의 -Djib.to.tags로 커밋해시를 이미지의 마지막에 접미사로 붙이고 싶어서 tags에 커밋해시를 붙이니
latest, 커밋해시 두개의 태그로 이미지가 푸시되어 추후에 argo imageUpdater에 불필요한 이미지를 트래킹하는 것을 제거하기 위해서 latest를 skip하고싶었으나 찾아보니 image를 명시하는 방법이 있어 image를 명시하는것으로 latest 태그는 push하지 않을 수 있었습니다
https://github.com/GoogleContainerTools/jib/issues/3346#issuecomment-880983881
Disable generating of the latest tag · Issue #3346 · GoogleContainerTools/jib
Environment: Jib version: 3.1.2 Build tool: Maven OS: any Description of the issue: I am using Immutable AWS ECR repository and when I run mvn clean install jib:build it fails with an error that th...
github.com
참고:
jib 공식문서 faq: https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md#frequently-asked-questions-faq
jib/docs/faq.md at master · GoogleContainerTools/jib
🏗 Build container images for your Java applications. - GoogleContainerTools/jib
github.com
oci: http://www.opennaru.com/kubernetes/open-container-initiative/
컨테이너 기술에 대한 표준화 – OCI ( OPEN CONTAINER INITIATIVE )
컨테이너 기술에 대한 표준화 단체인 Open Container Initiative는 2015 년 6 월에 레드햇, Docker, CoreOS, Google, IBM Red Hat, Amazon Web Services, VMware,The Linux Foundation 등이
www.opennaru.com
jib-gradle-plugin: https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin#quickstart
jib/jib-gradle-plugin at master · GoogleContainerTools/jib
🏗 Build container images for your Java applications. - GoogleContainerTools/jib
github.com
docker 계정 & token 생성: https://docs.docker.com/security/for-developers/access-tokens/
Create and manage access tokens
Learn how to create and manage your personal Docker access tokens to securely push and pull images programmatically.
docs.docker.com
'Web Application 운영' 카테고리의 다른 글
API 설계 원칙 (1) | 2024.07.23 |
---|