1. 개요
프로젝트에서 CI/CD는 선택이 아닌 필수(?) 가 되어가고 있는데요, 멀티 모듈을 도입하면서 조금 더 복잡해진 CI/CD 배포일지를 한번 작성해보고자 합니다.
2. 시스템 아키텍쳐
프로젝트 당시 작성했던 시스템 아키텍쳐의 일부분입니다. 실제로 Github Action과 Docker를 사용해서 CI/CD 환경을 구축했습니다.
흐름을 간단히 설명하면 다음과 같습니다.
1.
main 혹은 dev 브랜치에 push/pull_request 한다.
2.
테스트 진행 후 문제 없다면 deploy 단계를 거친다.
3.
Docker Hub에 빌드한 이미지를 push 한다.
4.
EC2 내에 접속한 뒤 Docker Hub에 있는 이미지를 pull 한다.
5.
Docker Compose를 통해 실행한다.
하지만 실제 구현은 굉장히 어려웠습니다.
멀티 모듈 아키텍쳐로 구성해 빌드할 자바 애플리케이션이 두 개 일 뿐만 아니라, Nginx, Certbot을 통한 HTTPS 설정 또한 CI/CD 과정에 같이 포함해야 했기 때문입니다.
3. 멀티 모듈 빌드
우선 애플리케이션 단에서 두 개의 작업을 해주어야 했습니다.
첫 번째는 Dockerfile을 작성해주는 것이고,
두 번째는 gradle에서 빌드 파일의 경로를 변경해주는 것이었습니다.
우선 각 애플리케이션을 Docker 이미지로 생성해야 하기 때문에 Dockerfile을 작성하였습니다. 예제는 다음과 같습니다.
# Docker 이미지의 기반이 되는 베이스 이미지를 지정
FROM eclipse-temurin:17
# 빌드 시점에 Docker 이미지 안으로 전달될 변수를 정의
ARG JAR_FILE=build/libs/api-server.jar
# `ARG`로 지정된 경로에서 JAR 파일을 Docker 이미지 내의 `api-server.jar`로 복사. 이렇게 함으로써 컨테이너가 실행될 때 필요한 실행 파일이 이미지 내에 포함
COPY ${JAR_FILE} api-server.jar
# 컨테이너가 시작될 때 실행될 명령어를 설정
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod,file-logging","-Duser.timezone=UTC","/api-server.jar"]
SQL
복사
프로젝트에서는 api-server, batch 두 개의 애플리케이션에 대해서 Docker 이미지로 배포가 필요했기 때문에 두 모듈에 Dockerfile을 작성해두었습니다.
다음으로 build.gradle에서 빌드 파일의 경로를 수정할 필요가 있었습니다.
String jarName = "api-server.jar"
tasks.named("bootJar") {
bootJar.getArchiveFileName().set(jarName)
bootJar.doLast(task -> {
copy(copySpec -> {
copySpec.from("build/libs/" + jarName)
copySpec.into("../build/libs")
})
})
}
SQL
복사
현재의 프로젝트 구조는 다음과 같습니다.
* root
└ .github
└ workflows
* ci.yml
* cd.yml
└ application
└ build/libs
└ batch
└ build/libs
└ build/libs
* docker-compose.yml
...
SQL
복사
빌드 된 .jar 파일을 Docker 이미지로 푸쉬하는 과정은 루트 디렉토리 (root) 에서 이뤄지기 때문에 각 애플리케이션 내의 build/libs가 아닌 부모 모듈의 build/libs에 저장하는 과정이 필요했습니다.
이로서 기본적인 구성을 설명드렸습니다.
다음 포스팅에서는 이 구성을 사용해서 어떻게 ci.yml 그리고 cd.yml을 작성하는지 알아보겠습니다.