Search

도커는 항상 어렵다 : 멀티모듈 CI/CD 배포일지

Tags

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을 작성하는지 알아보겠습니다.